Promise 在 JavaScript 中很早就有各种的开源实现,ES6 将其纳入了官方标准,提供了原生 api 支持,使用更加便捷。

定义

Promise 是一个对象,它用来标识 JavaScript 中异步操作的状态(pending, resolve, reject)及结果(data)。

从控制台打印出来一个Promise 对象来看下


可以看到,它是一个构造函数,既有属于自己私有的 resolve, reject, all, race等方法,也有protype 原型上的 then, catch等方法。

基本用法

  • 模拟问题:3秒后请求完成,返回数据res.data
var p = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('res.data');
  }, 3000);
});

p.then((val) => {
  console.log(val);
  // 'res.data'
});

console.log(p);
// [object Promise]

Promise.resolve() 的用法

Promise.resolve()方法可以将现有对象转为Promise 对象。

var p = Promise.resolve($.ajax('/something.data'));
p.then((val) => {console.log(val)});

它等价于
var p = new Promise(resolve => {
    resolve($.ajax('/something.data'))
});
p.then((val) => {console.log(val)});

Promise.reject() 用法

此方法和Promise.resolve()方法类似,除了rejecet 代表状态为 Rejected,不多说。

Promise.all() 用法

用于将多个Promise 实例包装成一个新的 Promise实例,参数为一组 Promise 实例组成的数组。

var p  = Promise.all([p1,p2,p3]);

当 p1, p2, p3 状态都 Resolved 的时候,p 的状态才会 Resolved;只要有一个实例 Rejected ,此时第一个被 Rejected 的实例的返回值就会传递给 P 的回调函数。

应用场景:假设有一个接口,需要其它两个接口的数据作为参数,此时就要等那两个接口完成后才能执行请求。

var p1 = new Promise((resolve, reject) => {
    setTimeout(resolve, 1000, 'P1');
});
var p2 = new Promise((resolve, reject) => {
    setTimeout(resolve, 2000, 'P2');
});
// 同时执行p1和p2,并在它们都完成后执行then:
Promise.all([p1, p2]).then((results) => {
    console.log(results); // 获得一个Array: ['P1', 'P2']
});

Promise.race() 用法

和Promise.all 类似,区别是 Promise.race() 只要监听到其中某一个实例改变状态,它的状态就跟着改变,并将那个改变状态实例的返回值传递给回调函数。

应用场景: 可以通过多个异步任务来进行容错处理,多个接口返回同样的数据,只要有一个接口生效返回数据即可。

Promise.prototype.then()

then 方法是定义在 Promise 的原型对象上的,作用是为 Promise 实例添加状态改变时的回调函数;

then() 返回一个新的Promise 实例,因此可以支持链式写法。

链式写法的一个例子//来自廖雪峰

// 0.5秒后返回input*input的计算结果:
function multiply(input) {
    return new Promise((resolve, reject) => {
        console.log('calculating ' + input + ' x ' + input + '...');
        setTimeout(resolve, 500, input * input);
    });
}

// 0.5秒后返回input+input的计算结果:
function add(input) {
    return new Promise((resolve, reject) => {
        console.log('calculating ' + input + ' + ' + input + '...');
        setTimeout(resolve, 500, input + input);
    });
}

var p = new Promise((resolve, reject) => {
    console.log('start new Promise...');
    resolve(123);
});

p.then(multiply)
 .then(add)
 .then(multiply)
 .then(add)
 .then(function (result) {
    console.log('Got value: ' + result);
});

Promise.prototype.catch()

catch 方法是一个语法糖,看下面代码就明白了,用于指定发生错误时的回调函数。

var p = new Promise((resolve, rejecet) => {
    if (...) {resolve()};
    else {reject()};
})
p.then((val) => {
    console.log('resolve:', val);
}).catch((err) => console.log('reject:', err));

// 等同于

p.then((data) => {
    console.log(data);
}, (err) => {
    console.log(err);
})

// 后一种写法更好,语义更清晰,第一种方法在第一个函数里面出错的话时在第二个函数里监听不到变化的。

Promise.try()

实际开发中,经常遇到一种情况:不知道或者不想区分,函数 f 是同步函数还是异步操作,但是想用 Promise 来处理它。因为这样就可以不管f是否包含异步操作,都用 then 方法指定下一步流程,用 catch 方法处理 f 抛出的错误。

  1. 第一种方法,缺陷是不能识别同步请求。
const f = () => console.log('now');
Promise.resolve().then(f);
console.log('next');
// next
// now
  1. new Promise() 写法
const f = () => console.log('now');
(
() => new Promise(
resolve => resolve(f())
)
)();
console.log('next');
// now
// next
  1. Promise.try 写法,替代new Promise() 方法,更简洁。
const f = () => console.log('now');
Promise.try(f);
console.log('next');
// now
// next

总结

两个特点

  1. 状态不受外界影响,只有异步操作的结果会影响到它,pending(进行中),reject(已失败),resolved(已完成)
  2. 状态只能改变一次

感受:

  1. promise 首先是一个构造函数,所以需要new 出来一个实例来使用
  2. 像是一个 ajax 函数外面加了一层包裹层,封装了一下下,实现了代码层面的同步效果
  3. 很有意思~(废话)
  4. 缺点也很明显,就是代码语义化不够,一眼看去都是Promise 的 API,then catch 等等,不能很快明白代码究竟想表达什么意思,这也是 async 函数出现的原因,async ,可能是异步操作的终极方案了。

最新文章

  1. C#中将DataTable导出为HTML的方法
  2. struts.xml配置详解 内部资料 请勿转载 谢谢合作
  3. 『TCP/IP详解——卷一:协议』读书笔记——16
  4. 无法启动此程序,因为计算机中丢失AdbWinApi.dll。尝试重新安装该程序以解决此问题
  5. 突破短板,传统桌面程序 使用webapi 扩展迎合web和移动端融合的需求
  6. ios 获取崩溃日志
  7. URAL 1097 Square Country 2 离散化
  8. 查询Table name, Column name, 拼接执行sql文本, 游标, 存储过程, 临时表
  9. A - Number Sequence(矩阵快速幂或者找周期)
  10. 初遇locust
  11. 10 Python+Selenium键盘事件
  12. Submin1安装记录(CentOS5)
  13. 201521123053《Java程序设计》第十一周学习总结
  14. Jenkins具体安装与构建部署使用教程
  15. Storyboard的几点缺憾
  16. SAP ERP SD模块中维护销售人员
  17. C#多线程和线程池问题
  18. 干货分享:vue2.0做移动端开发用到的相关插件和经验总结(2)
  19. CentOS Linux release 7.3源码安装zabbix
  20. Jenkins+Github配置【转】

热门文章

  1. 【U218】A-B
  2. 【u213&&t037】修剪花卉
  3. python property属性
  4. 古语云:工欲善其事必先利其器 --> 最新、最全的 IntelliJ IDEA(2018.3.3) 的介绍、安装、破解、配置与使用
  5. 【项目积累】对JSON数据的处理
  6. 【t006】三角形分形描绘问题
  7. Thermal management in a gaming machine
  8. 前端自动化之路之gulp,node.js
  9. unix shell(壳)的简单实现
  10. @AspectJ support (good)