为何Promise已解析为另一个Promise时状态仍显示pending?
Promise状态与微任务队列的疑问解析
先看代码片段:
var p3 = new Promise( function(resolve,reject){ resolve( "B" ); } ); var p1 = new Promise( function(res,rej){ resolve( p3 ); // equivalent to p3.then(res) } ); var p2 = new Promise( function(resolve,reject){ resolve( "A" ); } ); p1.then( function(v){ console.log("In p1"); console.log(p1); } ); p2.then( function(v){ console.log("In p2"); console.log(p1); } );
实际运行日志顺序是In p2先输出,且此时console.log(p1)显示pending,之后In p1输出,p1显示fulfilled。以下是对你的疑问和阶段理解的纠正:
纠正你对执行阶段的错误理解
- Stage 1:
resolve(p3)确实等价于p3.then(res),但res('B')的执行是异步的——不会在同步代码阶段立刻触发,所以此时p1的状态仍为pending。你说这个回调会被加入微任务队列(MTQ)是对的,但它的执行时机是在同步代码结束后,且实际运行中会排在p2的then回调之后。 - Stage 2:
p2的then回调被加入MTQ是对的,但此时MTQ中的顺序是p2的回调在前,p1的resolve回调在后,所以后续会先执行p2的回调。 - Stage 3:调用栈为空时,MTQ按先入先出执行,但你之前假设的执行顺序有误,实际是先执行
p2的then回调,此时p1的resolve回调还没执行,所以p1仍为pending。
你的疑问解答
当
res('B')执行时,是否会将p1的状态标记为Fulfilled?
是的。res就是p1绑定的resolve回调,调用它会同步把p1的状态改成fulfilled,并设置值为"B"。问题在于res('B')的执行是异步的,不会在同步代码阶段跑。既然
p1已完成且已注册处理函数,是否会被追加到MTQ中?
是的。一旦p1的状态变为fulfilled,之前通过p1.then注册的回调会被立即加入MTQ,等待执行。为何此时
p1仍显示为pending?
这里的"此时"指p2的then回调执行时,因为p2的then回调在MTQ中排在p1的resolve回调前面,先被执行了。此时p1的resolve回调还没来得及执行,所以状态还是pending。后续
p1为何突然变为fulfilled状态?p2的then回调执行完后,MTQ的下一个任务就是p1的resolve回调(也就是执行res('B')),这个任务执行时会把p1的状态改成fulfilled。之后p1的then回调被加入MTQ并执行,此时打印p1就会显示fulfilled。
内容的提问来源于stack exchange,提问作者Sadiq
相关产品推荐
相关产品推荐

