Promise.prototype.catch()

基线 广泛可用

此功能已得到良好建立,并且可在许多设备和浏览器版本上运行。它自以下时间起在浏览器中可用 2015 年 7 月.

catch() 方法是 Promise 实例的方法,用于安排在 promise 被拒绝时调用的函数。它立即返回另一个 Promise 对象,允许您 链接 到其他 promise 方法的调用。它是 then(undefined, onRejected) 的快捷方式。

试一试

语法

js
promiseInstance.catch(onRejected)

参数

onRejected

当此 promise 被拒绝时异步执行的函数。其返回值成为 catch() 返回的 promise 的完成值。该函数使用以下参数调用

reason

promise 被拒绝时的值。

返回值

返回一个新的 Promise。无论当前 promise 的状态如何,此新 promise 在返回时始终处于挂起状态。如果调用了 onRejected,则返回的 promise 将根据此调用的返回值解析,或拒绝此调用的抛出错误。如果当前 promise 完成,则不会调用 onRejected,并且返回的 promise 完成到相同的值。

描述

catch 方法用于 promise 组合中的错误处理。由于它返回一个 Promise,因此它 可以像其姊妹方法 then() 一样链接。

如果 promise 被拒绝,并且没有拒绝处理程序可调用(可以通过 then()catch()finally() 中的任何一个附加处理程序),则主机将显示拒绝事件。在浏览器中,这会导致 unhandledrejection 事件。如果处理程序附加到已导致未处理拒绝事件的已拒绝 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("oh, no!");
})
  .catch((e) => {
    console.error(e); // "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 已完成,则不会调用 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 语言规范
# sec-promise.prototype.catch

浏览器兼容性

BCD 表格仅在启用 JavaScript 的浏览器中加载。

另请参阅