六、Promise API 概述
6.1 new Promise(..) 构造器
构造器 Promise(..)
必须和 new
一起使用,并且必须提供一个函数回调。这个回调是同步的或立即调用的。这个函数接受两个函数回调,用以支持 Promise 的决议。通常我们把这两个函数称为 resolve(..)
和 reject(..)
:
let p = new Promise((resolve, reject) => {
// resolve(..) 用于决议/完成这个 promise
// reject(..) 用于拒绝这个 promise
})
reject(..)
就是拒绝这个 promise
。
resolve(..)
既可能完成 Promise ,也可能拒绝,要根据传入的参数而定。如果传入的参数是一个非 Promise 、非 thenable 的立即值,那么这个 promise
就会用这个值完成。
如果传给 resolve(..)
的是一个真正的 Promise 或 thenable 值,这个值就会被递归展开,并且 promise
将取用其最终决议值或状态。
6.2 Promise.resolve(..) 和 Promise.reject(..)
Promise.reject(..)
用来创建一个被拒绝的 Promise ,下面两种方式是等价的:
let p1 = new Promise((resolve, reject) => {
reject('err')
})
let p2 = Promise.reject('err')
传入 Promise.reject(..)
的参数,会原封不动的返回,
Promise.resolve(..)
用来创建一个已完成的 Promise ,下面两种方式是等价的:
let p1 = new Promise((resolve, reject) => {
resolve('ok')
})
let p2 = Promise.resolve('ok')
如果传入的是真正的 Promise , Promise.resolve(..)
什么都不会做,只会直接把这个值返回。
如果传入的是 thenable 值, Promise.resolve(..)
会展开 thenable 的值,返回的 Promise 采用这个 thenable 值的最终决议值,可能完成,也可能拒绝。
6.3 then(..) 、 catch(..) 和 finally(..)
每个 Promise 实例都有 then(..)
和 catch(..)
方法,通过这两个方法可以为这个 Promise 注册完成和拒绝处理函数。Promise 决议之后,会立即调用这两个处理函数之一,不会两个都调用,而且是异步调用的。
then(..)
接受一个或两个参数:第一个用于完成回调,第二个用于拒绝回调。如果两者中的任何一个被省略或者作为非函数值传入的话,就会替换为相应的默认回调:默认完成回调只是把消息传递下去,而默认拒绝回调则只是重新抛出其接收到的出错原因。
catch(..)
只接受一个拒绝回调作为参数,并自动替换默认拒绝回调,它等价于 then(null, rejected)
。
Promise 对象的错误具有“冒泡”性质,会一直向后传递,直到被捕获为止。也就是说,错误总是会被下一个 catch(..)
语句捕获。
一般来说,不要在 then(..)
方法里面定义 Reject 状态的回调函数(即 then 的第二个参数),总是使用 catch(..)
方法。
then(..)
和 catch(..)
也会创建并返回一个新的 promise
,这个 promise
可以用于实现 Promise 链式流程控制。
finally(..)
方法用于指定不管 Promise 对象最后状态如何,都会执行的操作。该方法是 ES2018 引入标准的。
promise
.then(result => {...})
.catch(error => {...})
.finally(() => {...})
上面代码中,不管 promise
最后的状态,在执行完 then
或 catch
指定的回调函数以后,都会执行 finally
方法指定的回调函数。
finally
方法的回调函数不接受任何参数,所以无法知道前面的 Promise 状态是完成还是拒绝。这说明 finally
方法里面的操作,应该是与状态无关的,不依赖于 Promise 的执行结果。
6.4 Promise.all([ .. ]) 和 Promise.race([ .. ])
参考上一篇
参考资料
- 《你不知道的JavaScript(中卷)》
- ES6教程(阮一峰)