Promise then 与 catch 的区别

then 第二个参数和 catch 方法在错误处理上的差异

问题

Promise 的 then 第二个参数和 catch 方法都能处理错误,它们有什么区别?

解答

then 的第二个参数

then 方法可以接收两个参数,第二个参数用于处理 Promise 被 rejected 的情况:

function asyncFunction() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      reject(new Error('Something went wrong'));
    }, 1000);
  });
}

asyncFunction()
  .then(
    result => console.log(result), 
    error => console.error(error)
  );

catch 方法

catch 方法本质上是 .then(null, errorHandler) 的语法糖,但它能捕获链式调用中前面所有的错误:

asyncFunction()
  .then(result => console.log(result))
  .catch(error => console.error(error));

关键差异

最重要的区别是错误捕获范围:

asyncFunction()
  .then(
    result => {
      throw new Error('Error in success handler');
    },
    error => console.error('不会捕获到上面的错误')
  );

asyncFunction()
  .then(result => {
    throw new Error('Error in success handler');
  })
  .catch(error => console.error('能捕获到上面的错误'));

then 的第二个参数只能捕获 Promise 本身的错误,无法捕获第一个参数(成功回调)中抛出的错误。而 catch 可以捕获前面整个链条中的所有错误。

关键点

  • then 第二个参数只捕获当前 Promise 的 rejection
  • catch 捕获链式调用中前面所有的错误,包括 then 成功回调中抛出的错误
  • catch 等价于 .then(null, errorHandler)
  • 推荐使用 catch 进行统一错误处理,代码更清晰