如何在客户端终止一个已经发出的HTTP请求
Javascript 異步編程得益于 Promise 的實(shí)現(xiàn),它們極大地提高了Web開發(fā)的性能和體驗(yàn)。不過(guò)原生的 Promise 有個(gè)最大的缺點(diǎn)就是一旦請(qǐng)求發(fā)出去,我們就無(wú)法取消它。但是我們找到了另一種方法來(lái)實(shí)現(xiàn)。
DOM 標(biāo)準(zhǔn)中添加了一個(gè)稱為 AbortController 的新的控制器,該控制器允許我們將其用作取消HTTP fetch 請(qǐng)求的信號(hào)。它利用 AbortSignal 屬性來(lái)執(zhí)行此操作。
它是在2017年添加的,并且在大多數(shù)瀏覽器中都支持(顯然,除了IE)。但是既然已經(jīng)拋棄對(duì)IE的支持,因此這真的是一件大事。
為什么我們需要取消 HTTP 請(qǐng)求?
在我們討論如何去取消之前,我們先了解下為什么需要取消 HTTP fetch 請(qǐng)求。當(dāng)我們的應(yīng)用程序是由可以動(dòng)態(tài)添加到 DOM 樹和從 DOM 樹刪除的多個(gè)組件組成的時(shí)候,許多組件都必須獨(dú)立進(jìn)行相應(yīng)的HTTP請(qǐng)求??赡馨l(fā)生的情況是,在獲取請(qǐng)求完成之前,將其中一個(gè)組件卸載。這種情況多發(fā)生在網(wǎng)速慢的情況下,或者在頁(yè)面正在跳轉(zhuǎn)時(shí)用戶離開了該頁(yè)面。
由于請(qǐng)求是異步的,因此它將在后臺(tái)繼續(xù)執(zhí)行。并且如果處理不當(dāng),可能會(huì)導(dǎo)致一些錯(cuò)誤。
谷歌瀏覽器的fetch請(qǐng)求默認(rèn)超時(shí)時(shí)間是300秒,火狐瀏覽器是90秒。這些還都是在網(wǎng)絡(luò)正常的情況下。因此,如果需要的話,我們絕對(duì)希望通過(guò)自己的方式來(lái)終止HTTP的fetch請(qǐng)求。
AbortController和AbortSignal
AbortController和AbortSignal API是由DOM標(biāo)準(zhǔn)提供,這樣即使Web標(biāo)準(zhǔn)變化了它仍然可以繼續(xù)使用。我們來(lái)聲明一個(gè)控制器:
const controller = new AbortController();和一個(gè)signal常量
const signal = controller.signal;這個(gè)控制器僅僅只有一個(gè)abort方法。并且該方法一旦被觸發(fā),立即通知signal
controller.abort(); signal.addEventListener('abort', () => {console.log(signal.aborted); // true });如何取消一個(gè)HTTP fetch請(qǐng)求
fetch Api本身不允許以編程方式取消請(qǐng)求。但是它可以將AbortSignal作為參數(shù)。這樣一來(lái),如果我們一旦需要,我們就可以在特定的時(shí)間段內(nèi)中止這個(gè)請(qǐng)求。
const controller = new AbortController(); const signal = controller.signal;fetch(url, { signal }).catch(err => {if (err.name === 'AbortError') {console.log('Fetch was aborted');}}); // Abort the request after 4s // aborts the fetch with 'AbortError' setTimeout(() => {controller.abort(); }, 4000);我們甚至可以自己封裝一個(gè)帶有延遲參數(shù)的fetch請(qǐng)求的函數(shù)
async function cancellableFetch(url, data, timeout = 4000) {const controller = new AbortController();const timer = setTimeout(() => controller.abort(), timeout);const response = await fetch(url, {...data,signal: controller.signal });clearTimeout(timer);return response; }值得注意的是:
如果我們將同一個(gè)signal傳遞給多個(gè)請(qǐng)求,如果一旦終止就取消了所有的請(qǐng)求。所以,它只能在如果一個(gè)請(qǐng)求失敗將取消所有請(qǐng)求的情況下使用。
由于控制器不能多次使用,如果我們不想在取消一個(gè)HTTP fetch請(qǐng)求時(shí)終止所有的請(qǐng)求,那么就需要為所有的控制器創(chuàng)建一個(gè)新的實(shí)例。
請(qǐng)求的取消僅發(fā)生在客戶端。盡管客戶端收不到響應(yīng),服務(wù)器仍可能會(huì)對(duì)其進(jìn)行處理。
我們也可以使用Promise.race來(lái)實(shí)現(xiàn)此功能,但是該解決方案會(huì)使請(qǐng)求掛起而不是中止請(qǐng)求。它將繼續(xù)在后臺(tái)消耗帶寬。
以上就是在耗時(shí)終止HTTP fetch 請(qǐng)求的方法,不知道有沒(méi)有疑問(wèn),歡迎留言!
總結(jié)
以上是生活随笔為你收集整理的如何在客户端终止一个已经发出的HTTP请求的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 仅使用HTML和CSS实现的标签云效果
- 下一篇: 【超详细教程】如何使用TypeScrip