如何中断一个正在发出的请求

在用户交互或者最新输入的时候,你经常须要在一个 web 应用中频繁发起请求。好比说在输入文字的时候的自动完成操做或者是在地图上放大缩小的操做。让咱们花一点时间去思考一下这些例子。首先是自动完成,每一次咱们输入的时候(或者更少在用 debounce 时)咱们就会发出一个请求。若是用户输入改变的时候,旧的请求就会与如今无关,当咱们持续打字输入的时候(好比 “java” 和 “javascript” )。也许有不少冗余请求,在咱们拿到咱们须要的东西的时候。javascript

而后是地图的例子。咱们在缩放查看地图的时候,咱们对于以前缩放级别的图块再也不感兴趣。与此同时,为了冗余数据,许多请求还处于等待。前端

带着咱们第一个例子,看看实现一个自动完成场景的原生代码。为了本文的目的,咱们将使用更现代的 fetch 而不是 XMLHttpRequest 来提出网络请求。 代码以下:java

autocompleteInput.addEventListener('keydown', function() {

    const url = "https://api.example.com/autocomplete"

    fetch(url)
        .then((response) => {
            // Do something with the response
            updateAutocompleteMenu()
        })
        .catch((error) => {
            // Something went wrong
            handleAutocompleteError(error);
        })

});
复制代码

这个例子的问题就是每个请求都要完成,即便它再也不相关。咱们能够实现一个额外的逻辑在 updateAutocompeleteMenu 中去防止额外的代码,可是却不能真正中止这个请求。值得注意的是,浏览器有同时请求的限制,这意味着一旦限制被触发时,请求将队列化(并且每一个浏览器限制又不一样)。git

Abortable Fetch

咱们能够用来解决上述问题的新浏览器技术是 Abortable Fetch 。 Abortable Fetch 依赖浏览器的规范 AbortController 。这个控制器有 signal 属性,咱们用它传递,在以后的时机中用控制器中断方法去取消请求。github

一个例子以下:web

autocompleteInput.addEventListener('keydown', function() {
const url = "https://api.example.com/autocomplete"
let controller;
let signal;

autocompleteInput.addEventListener('keyup', () => {

    if (controller !== undefined) {
        // Cancel the previous request
        controller.abort();
    }

    // Feature detect
    if ("AbortController" in window) {
        controller = new AbortController;
        signal = controller.signal;
    }

    // Pass the signal to the fetch request
    fetch(url, {signal})
        .then((response) => {
            // Do something with the response
            updateAutocompleteMenu()
        })
        .catch((error) => {
            // Something went wrong
            handleAutocompleteError(error);
        })
    });

});

复制代码

咱们进行特性检测,以肯定咱们是否可使用 AbortController (它在 Edge,Firefox,Opera 和 Chrome 66 中支持!)。咱们确认是否有一个控制器已经建立,若是是,咱们调用 controller.abort() 去取消以前的请求。你也能够一次用相同的 signal 取消多个 fetches 。api

一个小例子

我建立了一个展现如何使用 Abortable Fetch 小例子,基于自动完成场景的想法(没有任何实现细节!)。去理解每当输入网络请求时会发生什么。 若是您在旧请求完成以前进行了新的输入,它将停止先前的抓取。 在实践中它看起来有点像这样:promise

abortable fetch

源代码浏览器

深刻思考

也许 AbortController 最酷的部分是它被设计成一个停止异步任务的通用机制。它是 WHATWG specification 的一部分。这意味着它是DOM规范而不是语言(ECMAScript)规范,但对于前端开发来讲,这仍然是一个有用的功能。你能够利用它做为一个更清晰的异步控制流机制,用于实现异步任务的时候(即当使用 Promises 时)。这篇Bram Van Damme super article for a more detailed example 文章会有更多我所讲述的细节。网络

本翻译自原文 - Cancelling Requests with Abortable Fetch。不按期更新技术博文欢迎star。因为本人水平有限,错误之处在所不免,敬请指正!转载请注明出处,保留原文连接以及做者信息。

相关文章
相关标签/搜索