仅仅知道如何终止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咱们能够发现,其实主流浏览器大部分都支持了,若是咱们开发的平台很新仍是可使用的,相信不远的未来,确定会大批量使用。前端的道路也会愈来愈顺畅!

最后若是这边文章能帮给你带来一点帮助,欢迎关注,点赞,制做不易,与君共勉!