Promise.prototype.catch()

Baseline 已广泛支持

此特性已相当成熟,可在许多设备和浏览器版本上使用。自 ⁨2015 年 7 月⁩以来,各浏览器均已提供此特性。

catch() 方法用于安排一个函数在 Promise 被拒绝时调用。它会立即返回另一个 Promise 对象,允许你 链式调用 其他 Promise 方法。它是 then(undefined, onRejected) 的语法糖。

试一试

const promise = new Promise((resolve, reject) => {
  throw new Error("Uh-oh!");
});

promise.catch((error) => {
  console.error(error);
});
// Expected output: Error: Uh-oh!

语法

js
promiseInstance.catch(onRejected)

参数

onRejected

当此 Promise 被拒绝时异步执行的函数。它的返回值将成为 catch() 返回的 Promise 的 fulfilled 值。该函数会接收以下参数:

reason

Promise 被拒绝时附带的值。

返回值

返回一个新的 Promise。这个新 Promise 在返回时总是处于 pending 状态,无论当前 Promise 的状态如何。如果调用了 onRejected,则返回的 Promise 将根据该调用的返回值来 fulfilled,或根据该调用抛出的错误来 rejected。如果当前 Promise fulfilled,则不调用 onRejected,返回的 Promise 将以相同的值 fulfilled。

描述

catch 方法用于 Promise 组合中的错误处理。因为它返回一个 Promise,所以它可以像它的姊妹方法 then() 一样被 链式调用

如果一个 Promise 被拒绝,并且没有可调用的 rejection handlers(可以通过 then()catch()finally() 附加 handler),那么 rejection 事件将由宿主环境抛出。在浏览器中,这会触发一个 unhandledrejection 事件。如果已有一个 handler 附加到已被拒绝并导致了 unhandled rejection 事件的 Promise 上,则会触发另一个 rejectionhandled 事件。

catch() 在其被调用的对象上内部调用 then(),并传递 undefinedonRejected 作为参数。该调用的返回值将被直接返回。如果你包装了这些方法,这一点是可观察到的。

js
// overriding original Promise.prototype.then/catch just to add some logs
((Promise) => {
  const originalThen = Promise.prototype.then;
  const originalCatch = Promise.prototype.catch;

  Promise.prototype.then = function (...args) {
    console.log("Called .then on %o with arguments: %o", this, args);
    return originalThen.apply(this, args);
  };
  Promise.prototype.catch = function (...args) {
    console.error("Called .catch on %o with arguments: %o", this, args);
    return originalCatch.apply(this, args);
  };
})(Promise);

// calling catch on an already resolved promise
Promise.resolve().catch(function XXX() {});

// Logs:
// Called .catch on Promise{} with arguments: Arguments{1} [0: function XXX()]
// Called .then on Promise{} with arguments: Arguments{2} [0: undefined, 1: function XXX()]

这意味着传递 undefined 仍然会导致返回的 Promise 被拒绝,你需要传递一个函数来防止最终的 Promise 被拒绝。

因为 catch() 只是调用 then(),所以它支持子类化。

注意: 下面的示例抛出了 Error 实例。与同步的 throw 语句一样,这是被认为是良好的实践;否则,进行捕获的部分将不得不执行检查以确定参数是字符串还是错误,并且你可能会丢失诸如堆栈跟踪之类的宝贵信息。

示例

使用和链式调用 catch() 方法

js
const p1 = new Promise((resolve, reject) => {
  resolve("Success");
});

p1.then((value) => {
  console.log(value); // "Success!"
  throw new Error("oh, no!");
})
  .catch((e) => {
    console.error(e.message); // "oh, no!"
  })
  .then(
    () => console.log("after a catch the chain is restored"), // "after a catch the chain is restored"
    () => console.log("Not fired due to the catch"),
  );

// The following behaves the same as above
p1.then((value) => {
  console.log(value); // "Success!"
  return Promise.reject(new Error("oh, no!"));
})
  .catch((e) => {
    console.error(e); // Error: oh, no!
  })
  .then(
    () => console.log("after a catch the chain is restored"), // "after a catch the chain is restored"
    () => console.log("Not fired due to the catch"),
  );

抛出错误时的陷阱

抛出错误通常会调用 catch() 方法

js
const p1 = new Promise((resolve, reject) => {
  throw new Error("Uh-oh!");
});

p1.catch((e) => {
  console.error(e); // "Uh-oh!"
});

异步函数内部抛出的错误将表现得像未捕获的错误

js
const p2 = new Promise((resolve, reject) => {
  setTimeout(() => {
    throw new Error("Uncaught Exception!");
  }, 1000);
});

p2.catch((e) => {
  console.error(e); // This is never called
});

调用 resolve 后抛出的错误将被静默

js
const p3 = new Promise((resolve, reject) => {
  resolve();
  throw new Error("Silenced Exception!");
});

p3.catch((e) => {
  console.error(e); // This is never called
});

如果 Promise fulfilled,则不会调用 catch()

js
// Create a promise which would not call onReject
const p1 = Promise.resolve("calling next");

const p2 = p1.catch((reason) => {
  // This is never called
  console.error("catch p1!");
  console.error(reason);
});

p2.then(
  (value) => {
    console.log("next promise's onFulfilled");
    console.log(value); // calling next
  },
  (reason) => {
    console.log("next promise's onRejected");
    console.log(reason);
  },
);

规范

规范
ECMAScript® 2026 语言规范
# sec-promise.prototype.catch

浏览器兼容性

另见