Promise.prototype.catch()
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!
語法
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(),並傳遞 undefined 和 onRejected 作為引數。該呼叫的返回值將被直接返回。如果你包裝了這些方法,這一點是可觀察到的。
// 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(),所以它支援子類化。
示例
使用和鏈式呼叫 catch() 方法
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() 方法
const p1 = new Promise((resolve, reject) => {
throw new Error("Uh-oh!");
});
p1.catch((e) => {
console.error(e); // "Uh-oh!"
});
非同步函式內部丟擲的錯誤將表現得像未捕獲的錯誤
const p2 = new Promise((resolve, reject) => {
setTimeout(() => {
throw new Error("Uncaught Exception!");
}, 1000);
});
p2.catch((e) => {
console.error(e); // This is never called
});
呼叫 resolve 後丟擲的錯誤將被靜默
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()
// 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 |
瀏覽器相容性
載入中…