60 秒回答模板

Promise.then 返回的是一个新的 Promise,不是原来的 Promise。onFulfilled 或 onRejected 返回普通值时,新 Promise fulfilled,值就是返回值;回调里抛异常时,新 Promise rejected,原因是这个异常;回调返回另一个 Promise 或 thenable 时,新 Promise 会采用它最终的状态和值。如果 then 没有传对应回调,fulfilled 的值或 rejected 的原因会向后穿透。正因为 then 每次都生成新 Promise,才能链式串起同步返回、异步等待和错误传播。

考点 先明确返回新 Promise
主线 普通返回值会变成 fulfilled
易错点 说 then 返回原 Promise,解释不了为什么链…

深入解析

01

先明确返回新 Promise

p.then(fn) 的返回值是新 Promise。原 Promise 的状态一旦确定不会再变,链式调用靠新 Promise 承接下一步结果。

02

普通返回值会变成 fulfilled

回调 return 1、return 'ok' 或不写 return,都会让 then 返回的新 Promise fulfilled;不写 return 的值是 undefined。

03

抛异常会变成 rejected

回调执行期间 throw error,等价于返回的新 Promise 被 reject。后续可以通过 catch 或第二个 then 参数捕获。

04

返回 Promise 会被展开

如果回调 return fetch() 或 return Promise.resolve(x),外层新 Promise 不会 fulfilled 成一个 Promise 对象,而是等待这个 Promise 的最终状态。thenable 也会按类似规则解析。

05

值穿透和错误穿透

then 没传 onFulfilled 时,成功值会继续传给后面的 then;没传 onRejected 时,拒因会继续向后传,直到被 catch 或 onRejected 捕获。

06

链式错误处理要谨慎

catch 本质也是 then(null, onRejected),catch 返回普通值会把链路恢复为 fulfilled;如果想继续失败,要重新 throw 或返回 rejected Promise。

易错点

  • 说 then 返回原 Promise,解释不了为什么链式调用每一步能拿到不同返回值。
  • 认为 then 回调返回 Promise 时下一步拿到的是 Promise 对象,而不是等待后的值。
  • catch 里吞掉错误后忘记重新 throw,导致后续链路误以为成功。
  • 不传 onRejected 时以为错误会消失,实际上拒因会继续向后穿透。

面试官追问

then 返回原 Promise 会有什么问题?

如果返回原 Promise,链式调用无法让每一步拥有自己的结果和错误状态,也无法表达回调返回值对下一步的影响。

then 里 return Promise.resolve(1) 和 return 1 区别是什么?

最终下一步拿到的值都是 1。区别是前者会经过 Promise 解析和等待流程,后者直接让新 Promise fulfilled。

catch 后面的 then 为什么还能执行成功回调?

如果 catch 捕获错误后返回普通值,它返回的新 Promise 会变成 fulfilled,后续 then 的成功回调就会执行。

then 第二个参数和 catch 有什么差异?

then(onFulfilled, onRejected) 的 onRejected 只能捕获前一个 Promise 的拒因,捕不到同一个 then 中 onFulfilled 抛出的异常;后接 catch 可以捕获前面链路抛出的异常。