如何在 JavaScript 中取消Promises?
JavaScript 中的 Promises 是管理異步操作的天賜之物,它提供了一種處理成功和失敗的簡潔方法。
但有一個微妙的挑戰(zhàn):從設(shè)計上講,Promises 擁抱了其異步性質(zhì),一旦啟動就無法直接停止。
在我們需要更精細控制的情況下,這可能會成為障礙,這時,我們就需要設(shè)計可取消的 Promises!
原始 Promise 的問題
想象一下獲取大文件或發(fā)出網(wǎng)絡(luò)請求。如果用戶決定在中途取消,該怎么辦?使用標準 Promise,會陷入困境。它會在后臺繼續(xù)運行,可能會浪費資源。
我們的目標:優(yōu)雅取消
我們希望為我們的 Promise 提供以下功能:
- 取消:發(fā)起取消請求。
- 指示狀態(tài):了解 Promise 是否已成功取消或已解決。
TaskCancelable 解決方案
以下是我們可以實現(xiàn) TaskCancelable 函數(shù)來增強我們的 Promise 的方法:
export const TaskCancelable = (task) => {
let _reject;
let isCancel = false;
const _status = Symbol("cancel");
const cancelP = new Promise((resolve, reject) => {
_reject = reject;
});
const p = Promise.race([task, cancelP]);
p.catch((reason) => {
if (reason === _status) {
isCancel = true;
}
});
p.cancel = () => {
_reject(_status);
return p;
};
p.isCancel = () => {
return isCancel;
};
return p;
};
解釋
Symbol("cancel"):我們使用 Symbol 來創(chuàng)建取消的唯一標識符。這可以防止與其他潛在錯誤發(fā)生沖突。
Promise.race([task, cancelP]):奇跡就在這里發(fā)生!我們將原始任務(wù) Promise 與 cancelP Promise 進行比賽。先解決或先拒絕的一方獲勝。
p.cancel():此自定義函數(shù)在調(diào)用時會拒絕 cancelP Promise,從而有效觸發(fā)取消。
p.isCancel():這個方便的方法讓我們可以檢查 Promise 是否確實被取消。
實際示例
讓我們看看如何使用 TaskCancelable:
// Simulate a long-running task
const longTask = new Promise((resolve) => {
setTimeout(() => {
resolve("Task complete!");
}, 3000);
});
const cancellableTask = TaskCancelable(longTask);
// Cancel after 1 second
setTimeout(() => {
cancellableTask.cancel();
}, 1000);
cancellableTask
.then((result) => console.log("Success:", result)) // Won't run
.catch(() => {
if (cancellableTask.isCancel()) {
console.log("Task was cancelled!");
} else {
console.log("Task failed for another reason");
}
});
結(jié)論
通過創(chuàng)建可取消的 Promises,我們在管理異步操作方面獲得了更大的靈活性。這種模式對于響應(yīng)式用戶界面和資源密集型任務(wù)至關(guān)重要,因為取消是這些任務(wù)的關(guān)鍵。