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