Introduction
Promise就像它的名字一样,是指在未来某个时间将会发生的事情。这个事情会生成一个结果,我们叫做Result。
Promise有三种状态:
- Pending: 初始状态,既不是成功状态,也不是失败状态。
- Fulfilled: 意味着操作成功完成。
- Rejected: 意味着操作失败。
这里,Fullfilled
和Rejected
又统称为Settled
。也就是说,一个Promise只要执行完毕有就算是Settled
了, 无论是成功还是失败。
Promise API
Promise.all
Promise.all
接收一个promise数组,返回一个新的promise。这个新的promise会在所有promise都resolve之后resolve,或者在任何一个promise reject之后reject。
1 | const promise1 = new Promise((resolve, reject) => { |
假设Promise 2 reject了,那么Promise.all
会reject,并且返回的promise的值是Promise 2 reject的值。
1 | const promise1 = new Promise((resolve, reject) => { |
output:
1 | Error: Promise 2 rejected |
注意,Promise.all大部分情况下是异步返回的,只有一种情况例外,那就是传递一个空数组。
1 | Promise.all([]); // 立即同步返回 Promise { [] } |
我们可以使用console.log
来验证上述代码是同步返回的
1 | console.log('start'); |
输出结果如下,可见Promise.all([])
是同步返回的。
1 | start |
除了传递空数组外,其他所有情况都是异步返回,比如直接传递非promise数组。
1 | const p = Promise.all([1, 2, 3]); // 异步返回。 |
思考题:
以下代码输会输出promise one running...
吗?
1 | const p1 = new Promise((resolve, reject) => { |
解析:会输出’promise one running…’, 虽然Promise.all
会在任何一个promise reject之后立即reject,但是剩下的promise还是会继续执行,直到resolve或者reject。注意这就是promise的不可取消性,如何要取消,请使用RxJS中的observable。
到这里我们需要总结一下Promise.all
的返回值,一共有以下几种情况:
- 所有promise都resolve,返回一个数组,数组中包含了所有promise的resolve值。
- 任何一个promise reject,返回的promise会reject,其值是第一个reject的promise的值。
- 传递一个空数组,返回的promise会立即resolve,值是一个空数组。
Promise.allSettled
这个方法与Promise.all
类似,不同的是,Promise.allSettled
会等待所有promise都settled之后返回。settled的意思是promise已经resolve或者reject了。
Promise.allSettled
的返回值是一个数组,数组中的每个元素都是一个对象,包含了promise的状态和值。
1 | const p1 = new Promise((resolve, reject) => { |
以上代码输出如下:
1 | [ |
Promise.any
输入的Promise数组中,任意一个promise resolve,返回的promise就resolve。如果所有的promise都reject,返回的promise就reject。
以下代码输出quick,因为p2
最快resolve。
1 | const p1 = Promise.reject(0); |
当所有promise都reject时,Promise.any
会返回``AggregateError`,这个错误包含了所有的reject值。
1 | const p1 = Promise.reject(0); |
如果给Promise.any
传递一个空数组,返回的promise会reject,错误信息是[AggregateError: All promises were rejected] { [errors]: [] }
.
Promise.race
这个API最简单了,看名字就知道了,谁先返回就是谁,不论是resolve还是reject。Promise.race
接收一个promise数组,返回一个新的promise。这个新的promise会在任意一个promise resolve或者reject之后resolve或者reject。
下面代码输出two,因为p2
最快resolve。
1 | const p1 = new Promise((resolve, reject) => { |
注意:如果给Promise.race
传递一个空数组,返回的promise会一直pending,因为没有promise可以resolve或者reject。这就好比一个没有人参加的百米赛跑,永远不会有人冲过终点。
Promise in setTimeout
setTimeout
is macro-task, and promise is micro-task. So the promise will be executed before the setTimeout.
1 | const promise1 = Promise.resolve('Promise 1 resolved'); |
output:
1 | Promise { <pending> } |
Why the output?
Promise.all
is a micro-task, so it will be executed before thesetTimeout
macro-task.- The
promise
is pending when we log it for the first time. - After the
Promise.all
is executed, thepromise
is resolved - The
setTimeout
is a macro-task, so it will be executed after the queue is empty(no micro-task in the queue). - The
promise
is resolved when we log it for the second time