promise链中错误会向后传递直至被最近的.catch()捕获;.then的第二个参数仅捕获前级reject,不捕获自身回调抛出的错误;推荐统一用.catch()处理异常并显式传播错误。

Promise.then 和 Promise.catch 的错误处理,关键在于理解 Promise 链的错误传播机制——错误会一直向后传递,直到遇到第一个 .catch() 或带第二个参数的 .then()。
错误只被最近的 catch 捕获
一旦 Promise 被 reject,这个错误会跳过后续所有没有提供失败回调的 .then(),直到遇到 .catch() 或 .then(null, onError):
-
fetch('/api').then(res => res.json()).catch(err => console.error('网络或解析失败'))—— 这里 catch 同时捕获 fetch 失败和 JSON 解析异常 -
Promise.reject('oops').then(x => x).then(x => x).catch(e => console.log(e))—— 输出 'oops',因为错误一路透传到最终 catch
.then 的第二个参数 ≠ .catch
.then(successHandler, failureHandler) 中的 failureHandler 只捕获前一个 Promise 的 reject,不捕获 successHandler 内部抛出的错误;而 .catch() 会捕获链中任意位置(包括上一个 .then 成功回调里)抛出的错误:
-
Promise.resolve().then(() => { throw 'error in then' }).catch(e => e)→ 捕获到 'error in then' -
Promise.resolve().then(() => {}, () => 'ignored').then(() => { throw 'new error' }).catch(e => e)→ 捕获到 'new error',但第一个 .then 的第二个参数无法捕获它
避免“吞掉”错误
如果 .catch() 里没重新抛出错误或返回 rejected Promise,后续 .then 会继续执行(因为 catch 本身返回的是 resolved Promise):
-
Promise.reject('fail').catch(() => console.log('handled')).then(() => console.log('still runs'))→ 会输出两行 - 想让链中断并继续向下传递错误,需在 catch 中
throw err或return Promise.reject(err)
推荐写法:统一用 catch,不用 then 的第二个参数
更清晰、更不容易漏掉错误:
- 把业务逻辑全放在 .then() 的第一个参数里
- 用单独的 .catch() 统一处理链中任何环节的异常
- 必要时在 catch 里做日志、降级、重试,再决定是否继续传播










