JS Promise链式调用.then.catch执行顺序差异问题咨询
Promise 链式调用运行逻辑解答
核心前置规则
- 所有同步代码优先执行完毕,才会按先进先出的顺序执行微任务队列的任务
then/catch每次调用都会返回全新的Promise实例,后续链式方法都是绑定到这个新实例上,而非最初的Promise- 只有当某个Promise实例状态确定为fulfilled/rejected时,才会将它绑定的对应回调加入微任务队列,状态传递本身也会占用微任务位置
第一种情况:注释then(x => console.log(5)),输出1 6 3 7的原因
同步执行阶段
两个Promise链同步初始化完成后,微任务队列初始有2个任务:
- 第一个链的
then(x => console.log(1))回调(因为Promise.resolve(1)已经是fulfilled状态) - 第二个链第一个
then(x => console.log(4))的状态传递任务(因为Promise.reject(1)是rejected状态,这个then没有onRejected回调,返回的新Promise要继承rejected状态,这个处理需要占一个微任务位)
微任务执行流程
- 执行第一个任务:打印
1,这个then返回的Promise变为fulfilled,触发后续catch的状态传递任务加入微任务队列 - 执行第二个任务:第二个链第一个then返回的Promise变为rejected,触发后续
catch(x => console.log(6))回调加入微任务队列 - 现在队列里的任务顺序是「第一个链catch的状态传递任务」、「log6回调」
- 执行catch的状态传递任务:因为前序是fulfilled状态,catch不触发,直接触发后续
then(x => console.log(3))回调加入队列 - 执行log6回调:打印
6,这个catch返回的Promise变为fulfilled,触发后续then(x => console.log(7))回调加入队列 - 现在队列里的任务顺序是「log3回调」、「log7回调」,依次执行打印
3、7
最终输出顺序就是1 6 3 7
第二种情况:取消注释then(x => console.log(5)),输出1 3 6 7的原因
多出来的这个then会在第二个链上多一层Promise实例,多一次状态传递的微任务:
同步执行阶段
初始微任务队列还是2个任务:log1回调、第二个链第一个then的状态传递任务
微任务执行流程
- 执行第一个任务:打印
1,触发第一个链catch的状态传递任务加入队列 - 执行第二个任务:第二个链第一个then返回rejected,触发第二个链第二个
then(x => console.log(5))的状态传递任务加入队列 - 现在队列里的任务顺序是「第一个链catch的状态传递任务」、「第二个链第二个then的状态传递任务」
- 执行第一个链catch的状态传递任务:触发log3回调加入队列
- 执行第二个链第二个then的状态传递任务:这个then也没有onRejected回调,返回的Promise继承rejected,触发
catch(x => console.log(6))回调加入队列 - 现在队列里的任务顺序是「log3回调」、「log6回调」,依次执行打印
3、6 - log6执行完后触发log7回调加入队列,执行后打印
7
最终输出顺序就是1 3 6 7
内容的提问来源于stack exchange,提问作者snowy
相关产品推荐
相关产品推荐

