僅僅知道如何終止XHR請求,或許對你來講是不夠的!

TLDR:

當咱們須要的時候,咱們能夠經過AbortController接口來終止一個或者多個請求。javascript

前言

到目前爲止,咱們有兩個經常使用的基本的手段去發送請求進而局部刷新頁面內容,其一是XMR(XMLHttpRequest),其二是fetch,咱們一個個說html

XHR

對於XHR,咱們或許已經很熟悉了,當咱們想要發送一個請求的時候,咱們能夠這樣作:前端

const xhr = new XMLHttpRequest();
const method = 'GET';
const url = 'https://xxx';

xhr.open(method, url, true);
xhr.onreadystatechange = () => {
  if (xhr.readyState === 4) {
    // do something
  }
}
xhr.send();
複製代碼

當咱們因爲某種緣由(好比重複請求)想要終止它的時候,咱們只須要調用abort便可。java

xhr.abort();node

很方便也很簡潔,可是對於fetch呢?git

fetch

首先咱們看下fetch的基本定義:es6

看到這裏咱們已經知道了答案,可是咱們須要再去了解一下上文所說的AbortController.promise

AbortController

最初es6引入fetch的時候,其實就是沒有abort這樣的功能,不過廣大程序朋友們還會但願能有這個靈活的api,因此在2015年就有人提了這個issue,再次以後你們嘗試了注入promise式的取消或者是其餘hack等等,通過這份折騰最終咱們迎來了AbortController和AbortSignal。

AbortController目前很簡單,有一個制度的屬性AbortController.signal和一個用來中斷請求的.abort()

光說也沒啥意思,咱看代碼說話:

// 啓動一個node服務,其中包括一個api和一個html頁面

const Koa = require('koa');
const fs = require('fs');
const app = new Koa();

const sleep = () => {
    return new Promise(res => {
        setTimeout(function() {
            res();
        }, 3000);
    });
};

app.use(async ctx => {
    if (ctx.request.url === '/api') {
        await sleep();
        ctx.body = 'Hello World';
    } else {
        ctx.status = 200;
        ctx.respond = false;
        fs.createReadStream('./test.html').pipe(ctx.res);
    }
});

app.listen(3000);
複製代碼

下面是test.html的內容

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script> fetch('/api') .then((res) => { console.log(res, '請求成功'); }); </script>
</body>
</html>
複製代碼

啓動服務後,咱們看下network的內容。

咱們注意兩個地方,一個表明fetch請求,一個表明請求的延時時間,也就是咱們定義的三秒

取消fetch

這時候咱們想中斷,就能夠這樣作:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script> // 增長了以下幾行 const controller = new AbortController(); const signal = controller.signal; console.log(signal, 'signal的初始狀態'); signal.addEventListener('abort', function (e) { console.log(signal, 'signal的中斷狀態'); }); setTimeout(function() { controller.abort(); }, 2000); // 增長部分結束 fetch('/api', {signal}) .then((res) => { console.log(res, '請求成功'); }); </script>
</body>
</html>
複製代碼

再次運行,咱們會獲得以下結果:

從圖中咱們能夠很清楚的看到,請求在2s後被終止,請求狀態變爲canceled,而後aborted的狀態由false轉變爲true。

就是這樣,咱們對fetch也進行的取消操做,還算是豁然開朗吧。嘻嘻。

兼容性

雖然AbortController已經誕生很長時間了,可是目前mdn上的定義仍是實驗性技術,查看mdn咱們能夠發現,其實主流瀏覽器大部分都支持了,若是咱們開發的平臺很新仍是可使用的,相信不遠的未來,確定會大批量使用。前端的道路也會愈來愈順暢!

最後若是這邊文章能幫給你帶來一點幫助,歡迎關注,點贊,製做不易,與君共勉!

相關文章
相關標籤/搜索