new Promise((resolve,reject) => {
console.log('外部promise')
resolve()
})
.then(() => {
console.log('外部第一个then')
new Promise((resolve,reject) => {
console.log('内部promise')
resolve()
})
.then(() => {
console.log('内部第一个then')
return Promise.resolve()
})
.then(() => {
console.log('内部第二个then')
})
})
.then(() => {
console.log('外部第二个then')
})
.then(() => {
console.log('外部第三个then')
})
.then(() => {
console.log('外部第四个then')
})
一开始的理解:
- 实例化 promise,输出“外部promise”
- 执行外部第一个then,回调函数进入队列,外部的第二个、第三个和第四个then依次执行,但由于各自前面的promise都还没有resolve,所以回调函数暂时没有进入队列
- 执行外部第一个then的回调函数,输出“外部第一个then”,实例化另一个promise,输出“内部promise”
- 执行内部第一个then,回调函数进入队列,由于这个then返回的promise 还没resolve,所以后面跟着的内部第二个then的回调函数暂时没有进入队列
- 到这里,外部第一个then的回调执行完了,这个then返回的promise也resolve了,于是外部第二个then的回调进入队列
- 执行内部第一个then的回调函数,输出“内部第一个then”,之后返回一个resolve状态的promise,由于这个then的回调执行完了,所以内部第二个then的回调进队列
- 执行队列队头第一个回调,输出“外部第二个then”,同时让外部第三个then的回调进队列,接着执行内部第二个then的回调,输出“内部第二个then”
- 接着执行外部第三个then的回调,输出“外部第三个then”,同时让外部第四个then的回调进队列
- 最后执行外部第四个then的回调,输出“外部第四个then”
所以,输出的顺序应该是:
外部promise
外部第一个then
内部promise
内部第一个then
外部第二个then
内部第二个then
外部第三个then
但代码在chrome运行的时候,输出结果是:
外部promise
外部第一个then
内部promise
内部第一个then
外部第二个then
外部第三个then
外部第四个then
内部第二个then
这里不理解的地方就是,为什么外部所有then的回调都执行之后,最后再来执行内部第二个then的回调?这个和分析的结果不一样。然后我又将代码中的 return Promise.resolve()
去掉,发现打印结果和猜测结果就是一样的了,所以这里的重点应该在于 return Promise.resolve()
,但我不太清楚它具体是做了什么,导致代码输出顺序和预想的不一样。请教各位大佬。
then
返回的是一个 Promise (promise.prototype.then)。 这个 Promise 是使用then
的回调函数的返回值来 resolve 的。(已经 fulfilled 的 Promise 调用 then ,加入队列并不是直接是回调函数,而是 NewPromiseReactionJob 生成的一个任务。这个任务调用了 then 的回调,并使用这个回调的返回值 resolve then 返回的 Promise)
这里,回调返回的是 Promise().resolve()。这也是一个 Promise 。于是出现了用 Promise 来 resolve Promise 的情况。
用 Promise(0) 来 resolve Promise(1) 有些特殊。Promise(1) 的状态(pending/resolve/reject) 要根据 Promise(0) 来决定,而不是一定会进入 resolved 的状态。即使 Promise(0) 已经是 resolved 了,Promise(1) 也不会立即 resolve 。
(一般的 Promise resolve 里流程见 Promise Reolve Functions。当使用 Promise (严格的说,是 thenable ,即有 then 函数的 object ) 来 resolve Promise 的时候,会通过 NewPromiseResolveThenableJob 生成一个任务,加入队列。生成的这个任务会调用 then)
此时,微任务队列里会加入如下的一个(生成的)微任务(无论 Promise(0) 是什么状态),这个微任务调用 Promise(0) 的 then ,并在这个
then
的回调里 resolve 或者 reject Promise(1)。
这里 Promise(0) 就是 (return)
Promise.resolve()
,而 Promise(1) 是 “内部第一个then返回的 Promise”这里并没有执行“内部第二个then”,而是执行上面所述的微任务。
此时 Promise(0) (也就是“内部第一个then”里的
Promise.resolve()
)的 then 被执行。由于其已经是 resolved 状态,所以其回调被加入队列。被压入队列的这一个回调执行时会将 Promise(1) (也就是“内部第一个then”返回的 Promise)设置为 resolved 状态。
( NewPromiseResolveThenableJob 生成的任务执行,调用 then ,其回调为 Promise(1) 的 resolve function )
在此之后,7 中入队的回调被执行,“内部第一个then”返回的Promise 终于 resolve 了,于是它的 then 的回调(“内部第二个then”)终于被加入队列了。
在此之后,“内部第二个then” 执行。