[英]What is the equivalent of not calling a callback when inside an async function?
在異步/等待之前,當我的代碼使用回調時,我能夠做三件事:(1)使用結果調用回調,(2)使用錯誤調用回調,或者(3)完全不調用回調。
情況(3)用於以下情況:假設您有一個縮放按鈕,並且用戶可以單擊它來以更高的分辨率渲染圖像,這是一個異步過程。 如果用戶再次單擊縮放按鈕,則第一個渲染不再相關,可以取消以使新的縮放級別渲染運行。 我通過從函數內部返回而不調用回調來處理此問題,例如
if (process.wasCanceled()) {
return;
}
// ...
callback(someResult);
使用async / await,您只能做兩件事:返回或拋出。 當前,我一直在使用throw指示操作已取消,因為返回可能錯誤地指示上游進程應繼續運行。 但是拋出的問題是,所有上游調用者本身都需要知道這實際上不是錯誤,因此他們可能需要檢查錯誤的類型。
我的另一個瘋狂想法是創造一個永遠不會回報的承諾。 例如await never()
,其中函數定義如下:
async function never () {
return new Promise(function () {});
}
這相當於不調用回調。
但是我不知道那是否會一遍又一遍地泄漏內存。
有沒有上面提到的缺點的更好的等效方法?
如果絕對必要,您可以等待一個永遠不會返回的承諾。 這相當於不調用回調。
async function never () {
return new Promise(function () {});
}
async function op (process) {
// ...
if (process.wasCanceled()) await never();
// ...
}
根據這些答案,這將被垃圾回收,因為從不使用返回的promise,並且promise的function參數內部沒有與堆的連接。
但是,這很可能不是您想要執行的操作,因為上游呼叫者可能想知道其操作已被取消。 如果操作是由用戶通過UI啟動的,那么可以,在不通知調用方的情況下取消操作可能沒問題,但是,如果該操作是通過編程方式啟動的,並且已通過其他方式(例如,由用戶取消),則調用代碼可能需要知道以便它可以重試或清理資源。
因此,解決方案是拋出特定類的錯誤,以便調用者可以檢測到該進程已取消。 例如
class ProcessCanceledError extends Error {
...
}
async function render (process) {
while (...) {
// do some rendering
await delay(20);
if (process.wasCanceled()) throw new ProcessCanceledError();
}
}
var zoomProcess;
async function zoom () {
let process = new Process();
if (zoomProcess != null && !zoomProcess.isDone()) {
zoomProcess.cancel();
}
try {
await render();
} catch (e) {
// or you could do e.process === process
if (e instanceof ProcessCanceledError &&
process.wasCanceled() // make sure it was actually ours
) {
// this assumes we are a top level function
// otherwise, you would want to propagate the error to caller's caller
return;
}
throw e;
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.