为何Promise执行结果不符合预期?解析两种链式调用差异
Promise链式调用执行顺序差异解析
要搞懂这两段代码的执行差异,得先明确Promise链式调用的几个核心规则:
then/catch都会返回新的Promise实例,新实例的状态由回调函数的返回值决定(没显式返回时,默认返回resolved状态的undefined)- 只有当前Promise处于
rejected状态时,才会触发后续的catch回调;如果是resolved状态,会直接跳过catch执行下一个then then/catch的回调都是微任务,会在当前宏任务执行完毕后,按加入队列的顺序依次执行- 如果
then只传入了成功回调(没传错误处理的第二个参数),当它接收到rejected状态的Promise时,不会处理这个错误,而是直接将rejected状态传递给下一个Promise
第一段代码执行流程
两段代码的第一个Promise链完全一致,先看这个链:
Promise.resolve(1) .then(x => console.log(1)) .catch(x => console.log(2)) .then(x => console.log(3))
Promise.resolve(1)生成一个resolved状态的Promise,值为1- 第一个
then的回调加入微任务队列,执行时输出1,返回resolved状态的undefined - 后续的
catch因为前面是resolved状态,回调不会执行,直接返回resolved状态的undefined - 最后一个
then的回调加入队列,执行时输出3
再看第二个Promise链:
Promise.reject(2) .then(x => console.log(4)) .catch(x => console.log(6)) .then(x => console.log(7))
Promise.reject(2)生成一个rejected状态的Promise,值为2- 第一个
then只有成功回调,无法处理rejected状态,所以返回的新Promise也是rejected状态,回调不执行 - 后续的
catch接收到rejected状态,回调加入队列,执行时输出6,返回resolved状态的undefined - 最后一个
then的回调加入队列,执行时输出7
微任务队列执行顺序:
初始队列:[链1.then1, 链2.then1]
- 执行链1.then1 → 输出
1,将链1.catch加入队列 → 队列:[链2.then1, 链1.catch] - 执行链2.then1 → 无输出,将链2.catch加入队列 → 队列:[链1.catch, 链2.catch]
- 执行链1.catch → 无输出,将链1.then3加入队列 → 队列:[链2.catch, 链1.then3]
- 执行链2.catch → 输出
6,将链2.then3加入队列 → 队列:[链1.then3, 链2.then3] - 执行链1.then3 → 输出
3 - 执行链2.then3 → 输出
7
最终结果:1 6 3 7
第二段代码执行流程
差异只在第二个Promise链,新增了一个then:
Promise.reject(2) .then(x => console.log(4)) .then(x => console.log(5)) .catch(x => console.log(6)) .then(x => console.log(7))
Promise.reject(2)生成rejected状态的Promise- 第一个
then无错误处理,返回rejected状态的Promise,回调不执行 - 第二个
then同样只有成功回调,无法处理rejected状态,返回rejected状态的Promise,回调不执行 - 后续的
catch接收到rejected状态,回调加入队列,执行时输出6,返回resolved状态的undefined - 最后一个
then的回调加入队列,执行时输出7
微任务队列执行顺序:
初始队列:[链1.then1, 链2.then1]
- 执行链1.then1 → 输出
1,将链1.catch加入队列 → 队列:[链2.then1, 链1.catch] - 执行链2.then1 → 无输出,将链2.then2加入队列 → 队列:[链1.catch, 链2.then2]
- 执行链1.catch → 无输出,将链1.then3加入队列 → 队列:[链2.then2, 链1.then3]
- 执行链2.then2 → 无输出,将链2.catch加入队列 → 队列:[链1.then3, 链2.catch]
- 执行链1.then3 → 输出
3 - 执行链2.catch → 输出
6,将链2.then3加入队列 → 队列:[链2.then3] - 执行链2.then3 → 输出
7
最终结果:1 3 6 7
差异核心原因
第二段代码中,第二个Promise链多了一个无错误处理的then,这个then会在微任务队列中多插入一个“无输出”的执行步骤,导致链1的最后一个then(输出3)被提前到链2的catch(输出6)之前执行,最终改变了输出顺序。
内容的提问来源于stack exchange,提问作者Anonymous
相关产品推荐
相关产品推荐

