关于Promise 中then 挂载的任务,为交替执行。
1 | Promise.resolve().then(() => { |
输出结果为 0 2 1 3
.
原因是因为每次 then
方法都是返回了一个新的 Promise
,那么其实每次resolve的时候只是将当前的 Promise的 onFulfilled
推入到微任务队列中。
当前一次的 Promise的 onFulfilled 执行时,才通过 resolvePromise
开始执行下一个新的 Promise
的resolve.
那么如果同时存在多个 Promise的话,那么首次推出到 微任务队列则是同时进入的,就相当于是 一批一批 的进行处理。
但是如果onFulfilled 中的返回值为一个新的Promise
的话,那么这里就需要涉及到Promise
的展开问题。但是整体的外层的 onFulfilled
的执行顺序还是保持不变。
Promise 展开问题
1 | Promise.resolve().then(() => { |
输出结果为 0 1 2 3 4
但是上面这个代码如果把 return
关键字去掉的话,结果又有点变化:
1 | Promise.resolve().then(() => { |
1 | Promise.resolve().then(() => { |
输出结果为 0 1 4 2 3
关于为啥多了一个 return
就会多了这么多的幺蛾子,主要是由于 onFulfilled
方法的返回值导致的问题,如果该方法的返回值是一个 Promise 的话,那么将会涉及到它的展开。
其实就是进行重新的 resolvePromise
。并且会 调用 新返回的 Promise 的 then
方法添加一个 微任务。
- 2.3.3. Otherwise, if x is an object or function,
- 2.3.3.1 Let then be x.then. [3.5]
- 2.3.3.2 If retrieving the property x.then results in a thrown exception e, reject promise with e as the reason.
- 2.3.3.3 If then is a function,
call it with x as this
, first argument resolvePromise, and second argument rejectPromise, where:
然后通过 闭包 将之前产生的 promise2 和现在的返回新的 promise进行连接。
1 | resolvePromise(promise2, x, resolve, reject) |
1 | then.call( |
题外话:可能还有一个地方需要注意的是,其实在then方法进行调用的时候,并没有所谓的立刻加入到 微任务队列中,只是加入了一个function到 其 onfulfilledcallback队列中。
真正加入到 微任务队列其实是在被决议也就是 resolve的时候才被添加到 宿主环境的 微任务队列中(这也是为什么多个Promise实例的执行顺序时候交替执行的)。
正是因为只是被加入到Promise的队列中,那么才有可能实现将返回的promise和之前已经写好的then方法返回的promise进行连接。
PromiseA+ 规范实现
1 | /** |
最后附上 PromiseA+ 规范: Promise