W3Cschool
恭喜您成為首批注冊用戶
獲得88經(jīng)驗(yàn)值獎勵
正如我們所知道的,?fetch
? 返回一個 promise。JavaScript 通常并沒有“中止” promise 的概念。那么我們怎樣才能取消一個正在執(zhí)行的 ?fetch
? 呢?例如,如果用戶在我們網(wǎng)站上的操作表明不再需要某個執(zhí)行中的 ?fetch
?。
為此有一個特殊的內(nèi)建對象:AbortController
。它不僅可以中止 fetch
,還可以中止其他異步任務(wù)。
用法非常簡單。
創(chuàng)建一個控制器(controller):
let controller = new AbortController();
控制器是一個極其簡單的對象。
abort()
?,signal
?,我們可以在這個屬性上設(shè)置事件監(jiān)聽器。當(dāng) abort()
被調(diào)用時:
controller.signal
? 就會觸發(fā) ?abort
? 事件。controller.signal.aborted
? 屬性變?yōu)?nbsp;?true
?。通常,我們需要處理兩部分:
controller.signal
? 上添加一個監(jiān)聽器,來執(zhí)行可取消操作。controller.abort()
?。這是完整的示例(目前還沒有 fetch
):
let controller = new AbortController();
let signal = controller.signal;
// 執(zhí)行可取消操作部分
// 獲取 "signal" 對象,
// 并將監(jiān)聽器設(shè)置為在 controller.abort() 被調(diào)用時觸發(fā)
signal.addEventListener('abort', () => alert("abort!"));
// 另一部分,取消(在之后的任何時候):
controller.abort(); // 中止!
// 事件觸發(fā),signal.aborted 變?yōu)?true
alert(signal.aborted); // true
正如我們所看到的,AbortController
只是在 abort()
被調(diào)用時傳遞 abort
事件的一種方式。
我們可以自己在代碼中實(shí)現(xiàn)相同類型的事件監(jiān)聽,而不需要 AbortController
對象。
但是有價(jià)值的是,fetch
知道如何與 AbortController
對象一起工作。它們是集成在一起的。
為了能夠取消 fetch
,請將 AbortController
的 signal
屬性作為 fetch
的一個可選參數(shù)(option)進(jìn)行傳遞:
let controller = new AbortController();
fetch(url, {
signal: controller.signal
});
fetch
方法知道如何與 AbortController
一起工作。它會監(jiān)聽 signal
上的 abort
事件。
現(xiàn)在,想要中止 fetch
,調(diào)用 controller.abort()
即可:
controller.abort();
我們完成啦:fetch
從 signal
獲取了事件并中止了請求。
當(dāng)一個 fetch 被中止,它的 promise 就會以一個 error AbortError
reject,因此我們應(yīng)該對其進(jìn)行處理,例如在 try..catch
中。
這是完整的示例,其中 fetch
在 1 秒后中止:
// 1 秒后中止
let controller = new AbortController();
setTimeout(() => controller.abort(), 1000);
try {
let response = await fetch('/article/fetch-abort/demo/hang', {
signal: controller.signal
});
} catch(err) {
if (err.name == 'AbortError') { // handle abort()
alert("Aborted!");
} else {
throw err;
}
}
AbortController
是可伸縮的。它允許一次取消多個 fetch。
這是一個代碼草稿,該代碼并行 fetch 很多 urls
,并使用單個控制器將其全部中止:
let urls = [...]; // 要并行 fetch 的 url 列表
let controller = new AbortController();
// 一個 fetch promise 的數(shù)組
let fetchJobs = urls.map(url => fetch(url, {
signal: controller.signal
}));
let results = await Promise.all(fetchJobs);
// controller.abort() 被從任何地方調(diào)用,
// 它都將中止所有 fetch
如果我們有自己的與 fetch
不同的異步任務(wù),我們可以使用單個 AbortController
中止這些任務(wù)以及 fetch。
在我們的任務(wù)中,我們只需要監(jiān)聽其 abort
事件:
let urls = [...];
let controller = new AbortController();
let ourJob = new Promise((resolve, reject) => { // 我們的任務(wù)
...
controller.signal.addEventListener('abort', reject);
});
let fetchJobs = urls.map(url => fetch(url, { // fetches
signal: controller.signal
}));
// 等待完成我們的任務(wù)和所有 fetch
let results = await Promise.all([...fetchJobs, ourJob]);
// controller.abort() 被從任何地方調(diào)用,
// 它都將中止所有 fetch 和 ourJob
AbortController
? 是一個簡單的對象,當(dāng) ?abort()
? 方法被調(diào)用時,會在自身的 ?signal
? 屬性上生成 ?abort
? 事件(并將 ?signal.aborted
? 設(shè)置為 ?true
?)。fetch
? 與之集成:我們將 ?signal
? 屬性作為可選參數(shù)(option)進(jìn)行傳遞,之后 ?fetch
? 會監(jiān)聽它,因此它能夠中止 ?fetch
?。AbortController
??!罢{(diào)用 ?abort()
?” → “監(jiān)聽 ?abort
? 事件”交互簡單且通用。即使沒有 ?fetch
?,我們也可以使用它。Copyright©2021 w3cschool編程獅|閩ICP備15016281號-3|閩公網(wǎng)安備35020302033924號
違法和不良信息舉報(bào)電話:173-0602-2364|舉報(bào)郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號
聯(lián)系方式:
更多建議: