已立即resolve的Promise作为参数传入另一Promise时的行为疑问
Promise嵌套解析的执行机制疑问解答
问题背景
以下是来自《You Don't Know JS Async & Performance》的代码片段,笔者添加了console.log语句用于调试:
var promiseA = new Promise( function(resolve,reject){ resolve( "B" ); } ); console.log("promiseA",promiseA); var promiseB = new Promise( function(resolve,reject){ resolve( promiseA ); } ); console.log("promiseB",promiseB); var promiseC = new Promise( function(resolve,reject){ resolve( "A" ); } ); console.log("promiseC",promiseC); promiseB.then( function(v){ console.log( v ); } ); promiseC.then( function(v){ console.log( v ); } );
预期输出
promiseA Promise { 'B' } promiseB Promise { 'B' } promiseC Promise { 'A' } B A
实际输出
promiseA Promise { 'B' } promiseB Promise { <pending> } promiseC Promise { 'A' } A B
疑问
promiseA已立即resolve,为何同步执行脚本时promiseB仍处于pending状态,且then回调的执行顺序与预期不符?
问题解析
1. 同步阶段promiseB为何是pending?
Promise的resolve方法有特殊规则:当传入的参数是另一个Promise实例时,当前Promise不会直接继承它的状态,而是会启动一个异步的"状态跟踪"流程——它要等传入的Promise(这里是promiseA)状态确定后,再同步自身的状态和值。
同步代码执行到console.log("promiseB",promiseB)时,这个异步跟踪流程还没来得及运行,所以promiseB此时仍处于pending状态,要等当前同步任务全部执行完,进入微任务阶段后,才会完成状态同步。
2. 为什么then回调顺序是A先B后?
- promiseC的
resolve传入的是普通值"A",它的状态会立即变为resolved,调用promiseC.then()时,对应的回调会被直接加入微任务队列。 - 而promiseB的
resolve传入的是promiseA,哪怕promiseA已经resolved,这个"等待并同步状态"的过程依然是异步的,只有等这个异步流程完成后,promiseB的状态才会变为resolved,它的then回调才会被加入微任务队列。
所以微任务队列的顺序是先加入promiseC的回调,再加入promiseB的回调,执行时自然先输出"A",再输出"B"。
内容的提问来源于stack exchange,提问作者amt
相关产品推荐
相关产品推荐

