如何中止获取请求?

Posted

技术标签:

【中文标题】如何中止获取请求?【英文标题】:How to abort a fetch request? 【发布时间】:2017-06-19 04:55:59 【问题描述】:

我一直在使用新的fetch API 而不是旧的XMLHttpRequest

这很棒,但我缺少一个关键功能,xhr.abort()。

我找不到任何有关获取该功能的信息。

谢谢。

更新: 用于中止提取的 hacky 解决方法https://github.com/Morantron/poor-mans-cancelable-fetch

基本上你在 web worker 中启动 fetch 并取消 web worker 以中止 fetch

【问题讨论】:

那是因为你不能取消 fetch :( 见:github.com/tc39/proposal-cancelable-promises/issues/70 github.com/whatwg/fetch/issues/27 所以如果你真的需要中止请求,坚持使用 XHR How do I cancel an HTTP fetch() request?的可能重复 解决方法似乎有点过头了,我最好先填充 fetch 然后添加缺少的功能 来自 Google 的开发者网站:Abortable fetch 感谢您的更新!虽然这意味着您需要为每次提取创建并保留一个 AbortController ,但您希望能够中止(如果您可以中止一组提取,您将需要更少)并且在每次提取后销毁相应的已保存控制器 - 不意味着一个完美的解决方案,但比解决方法更好 【参考方案1】:

它仍然是一个悬而未决的问题 所有相关的讨论都可以在这里找到

https://github.com/whatwg/fetch/issues/447 :(

【讨论】:

【参考方案2】:

可以通过 AbortController 中止获取:

export function cancelableFetch(reqInfo, reqInit) 
  var abortController = new AbortController();
  var signal = abortController.signal;
  var cancel = abortController.abort.bind(abortController);

  var wrapResult = function (result) 
    if (result instanceof Promise) 
      var promise = result;
      promise.then = function (onfulfilled, onrejected) 
        var nativeThenResult = Object.getPrototypeOf(this).then.call(this, onfulfilled, onrejected);
        return wrapResult(nativeThenResult);
      
      promise.cancel = cancel;
    
    return result;
  

  var req = window.fetch(reqInfo, Object.assign(signal: signal, reqInit));
  return wrapResult(req);

用法示例:

var req = cancelableFetch("/api/config")
  .then(res => res.json())
  .catch(err => 
    if (err.code === DOMException.ABORT_ERR) 
      console.log('Request canceled.')
    
    else 
      // handle error
    
  );

setTimeout(() => req.cancel(), 2000);

链接:

    https://developers.google.com/web/updates/2017/09/abortable-fetch https://developer.mozilla.org/en-US/docs/Web/API/AbortController

【讨论】:

【参考方案3】:

我通常使用类似的东西,类似于@ixrock。

// Fetch and return the promise with the abort controller as controller property
function fetchWithController(input, init) 
  // create the controller
  let controller = new AbortController()
  // use the signal to hookup the controller to the fetch request
  let signal = controller.signal
  // extend arguments
  init = Object.assign(signal, init)
  // call the fetch request
  let promise = fetch(input, init)
  // attach the controller
  promise.controller = controller
  return promise

然后用

替换正常的 fetch
let promise = fetchWithController('/')
promise.controller.abort()

【讨论】:

以上是关于如何中止获取请求?的主要内容,如果未能解决你的问题,请参考以下文章

中止上一个后无法发出新的获取请求

如何取消/中止 jQuery AJAX 请求?

如何中止使用 wininet 发送的请求?

中止请求和超时 跨域的HTTP请求 认证方式 JSONP

取消(中止)异步请求

取消(中止)异步请求