标准答案
- 状态:Promise 有 pending、fulfilled、rejected 三种状态。状态只能从 pending 变成 fulfilled 或 rejected,一旦 settled 就不可逆,后续再次 resolve 或 reject 都不会改变结果。
- 链式调用:then、catch、finally 都会返回新的 Promise。then 回调返回普通值时,下一个 then 收到这个值;返回 Promise 或 thenable 时,下一个节点会等待它的状态和值。
- 错误穿透:错误会沿 Promise 链向后传播,直到被 catch 或 then 的 rejection 回调处理。catch 本质上是 then(null, onRejected),处理后如果返回正常值,链路会回到 fulfilled。
- finally:finally 适合做清理动作,不接收上一步业务结果,默认也不改变原来的值或错误。但如果 finally 内部抛错或返回 rejected Promise,后续链路会变成 rejected。
题目解析
Promise 的解析重点是“状态”和“链”。只说 pending、fulfilled、rejected 不够,还要说明状态不可逆,以及 then/catch/finally 每次都会返回新的 Promise。
then 返回新 Promise 以后,链式调用才能把普通值、抛出的错误、返回的 Promise 统一串起来。这个点解释清楚后,错误穿透、值传递、异步等待就都能顺下来。
finally 经常被误解成能拿到结果或修改结果。更准确地说,它主要用于清理,默认透传原来的值或错误;但它自己抛错或返回 rejected Promise 时,会覆盖后续链路状态。
Promise.resolve、thenable 和手写 Promise 会继续涉及“状态吸收”和“回调队列”。这些内容属于进一步展开,基础层面先把状态流转和值传递说清楚。
代码示例
这个例子能同时说明值传递、错误穿透和 finally 的清理语义。
JavaScript
Promise.resolve(1)
.then(value => value + 1)
.then(value => {
throw new Error('failed')
})
.then(() => {
console.log('skipped')
})
.catch(error => {
console.log(error.message) // failed
return 10
})
.finally(() => {
console.log('cleanup')
})
.then(value => {
console.log(value) // 10
})常见误区
- 误以为 Promise 状态可以多次改变。
- 忘记 then/catch/finally 都返回新的 Promise。
- 误以为 finally 能拿到上一步的业务结果。