Promise 的 then、catch、finally 怎样传递值和错误?

先理解原理和示例,再练习完整口述与追问。

then 成功回调的返回值成为下一个 Promise 的成功值;返回 thenable 会采纳它;抛错或返回拒绝的 Promise 会拒绝。catch 是只处理拒绝的 then。finally 不改成功值,回调抛错或返回拒绝时才会把链变成拒绝。非函数的处理函数会把状态原样往后传。

Promise 有 pending、fulfilled、rejected 三种状态,兑现或拒绝之后不能再变。then(onFulfilled, onRejected) 始终返回新的 Promise。处理函数返回普通值,新 Promise 以该值兑现;返回 thenable,就跟着那个 thenable 的结果走,这叫采纳;抛出异常,新 Promise 拒绝。因此拒绝可以被后面的成功返回值“接住”,后面的 .then 会走到成功分支。

省略处理函数,或传入的不是函数,对应状态会穿透到下一个 Promise。.then()、.then(null, null) 都是穿透。.catch(fn) 就是 .then(undefined, fn)。.finally(fn) 会等待 fn:fn 正常返回时,原成功值或原拒绝原因继续往下传,fn 的返回值被忽略;fn 抛错或返回一个拒绝的 Promise 时,链变成这个新的拒绝。它适合做收尾,不适合用来变换结果。

js
Promise.resolve(1).then().then(value => value) // 1,空 then 穿透
Promise.reject(new Error('x'))
  .catch(error => error.message) // 返回字符串,后续 then 得到 'x'
  .then(value => value)

Promise.resolve(1)
  .finally(() => 2)
  .then(value => value) // 1,finally 的 2 被忽略

Promise.resolve(1)
  .finally(() => Promise.reject(new Error('y')))
  .catch(error => error.message) // 'y'

在 then 里写出 promise.then(fn()) 会立刻执行 fn,传进去的是返回值而不是函数。忘记返回就会得到 undefined。catch 后面如果没有再抛出,调用方会以为整条链成功。

then 的回调返回普通值,下一个 Promise 就成功为这个值;返回 Promise 或 thenable 就采纳它的结果;抛错就拒绝。不是函数的处理器会把原来的成功或失败原样传下去,所以空 then 能穿透。catch 只接拒绝,它返回正常值后链会恢复成功。finally 做收尾,正常结束时不改原来的值或原因,只有它自己抛错或返回拒绝的 Promise,才会把链改成失败。