Promise.prototype.catch()

Promise 实例的 catch() 方法安排一个函数在 Promise 被拒绝时调用。它立即返回一个等效的 Promise 对象,允许你对其他 Promise 方法进行 chain 调用。这是 Promise.prototype.then(undefined, onRejected) 的快捷方式。

¥The catch() method of Promise instances schedules a function to be called when the promise is rejected. It immediately returns an equivalent Promise object, allowing you to chain calls to other promise methods. It is a shortcut for Promise.prototype.then(undefined, onRejected).

Try it

语法

¥Syntax

js
promiseInstance.catch(onRejected)

参数

¥Parameters

onRejected

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

reason

承诺被拒绝的值。

返回值

¥Return value

返回一个新的 Promise。无论当前 Promise 的状态如何,该新 Promise 在返回时始终处于待处理状态。如果调用 onRejected,则返回的 Promise 将根据此调用的返回值进行解析,或者拒绝此调用引发的错误。如果当前的 Promise 满足,则不会调用 onRejected 并且返回的 Promise 满足相同的值。

¥Returns a new Promise. This new promise is always pending when returned, regardless of the current promise's status. If onRejected is called, the returned promise will resolve based on the return value of this call, or reject with the thrown error from this call. If the current promise fulfills, onRejected is not called and the returned promise fulfills to the same value.

描述

¥Description

catch 方法用于 Promise 组合中的错误处理。由于它返回 Promise,因此它以与其姊妹方法 then() 相同的方式返回 可以被链接起来

¥The catch method is used for error handling in promise composition. Since it returns a Promise, it can be chained in the same way as its sister method, then().

如果 Promise 被拒绝,并且没有可调用的拒绝处理程序(可以通过 then()catch()finally() 中的任何一个附加处理程序),则主机会显示拒绝事件。在浏览器中,这会导致 unhandledrejection 事件。如果处理程序附加到被拒绝的 Promise,而该 Promise 的拒绝已经导致未处理的拒绝事件,则会触发另一个 rejectionhandled 事件。

¥If a promise becomes rejected, and there are no rejection handlers to call (a handler can be attached through any of then(), catch(), or finally()), then the rejection event is surfaced by the host. In the browser, this results in an unhandledrejection event. If a handler is attached to a rejected promise whose rejection has already caused an unhandled rejection event, then another rejectionhandled event is fired.

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

¥catch() internally calls then() on the object upon which it was called, passing undefined and onRejected as arguments. The value of that call is directly returned. This is observable if you wrap the methods.

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 被拒绝。

¥This means that passing undefined still causes the returned promise to be rejected, and you have to pass a function to prevent the final promise from being rejected.

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

¥Because catch() just calls then(), it supports subclassing.

注意:下面的例子是抛出 Error 的实例。与同步 throw 语句一样,这被认为是一个很好的实践;否则,执行捕获的部分必须执行检查以查看参数是字符串还是错误,并且你可能会丢失有价值的信息,例如堆栈跟踪。

¥Note: The examples below are throwing instances of Error. As with synchronous throw statements, this is considered a good practice; otherwise, the part doing the catching would have to perform checks to see if the argument was a string or an error, and you might lose valuable information such as stack traces.

示例

¥Examples

使用和链接 catch() 方法

¥Using and chaining the catch() method

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"),
  );

抛出错误时的陷阱

¥Gotchas when throwing errors

抛出错误大多数时候会调用 catch() 方法:

¥Throwing an error will call the catch() method most of the time:

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

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

异步函数内部抛出的错误将像未捕获的错误一样:

¥Errors thrown inside asynchronous functions will act like uncaught errors:

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 后抛出的错误将被静音:

¥Errors thrown after resolve is called will be silenced:

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

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

如果承诺完成,则不会调用 catch()

¥catch() is not called if the promise is fulfilled

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);
  },
);

规范

Specification
ECMAScript Language Specification
# sec-promise.prototype.catch

¥Specifications

浏览器兼容性

BCD tables only load in the browser

¥Browser compatibility

也可以看看