【问题标题】:How do I abort fetch request and start a new one immediately?如何中止获取请求并立即开始新的请求?
【发布时间】:2019-09-03 06:37:53
【问题描述】:

以下是来自 MDN 的示例。有两个按钮。一个正在发送请求,另一个正在取消。

var controller = new AbortController();
var signal = controller.signal;

var downloadBtn = document.querySelector('.download');
var abortBtn = document.querySelector('.abort');

downloadBtn.addEventListener('click', fetchVideo);

abortBtn.addEventListener('click', function() {
  controller.abort();
  console.log('Download aborted');
});

function fetchVideo() {
  ...
  fetch(url, {signal}).then(function(response) {
    ...
  }).catch(function(e) {
    reports.textContent = 'Download error: ' + e.message;
  })
}

现在我的情况不同了。我有一个 query 参数,如果正在获取但未完成,并且 query 参数发生更改 - 我如何发送一个新请求自动取消之前的请求?

【问题讨论】:

  • 你意识到这一点isn't supported on IE right?你的问题到底是什么?有没有办法做到这一点,是的。
  • Edge 上实际上支持 @Liam + IE 有 polyfills npmjs.com/package/abortcontroller-polyfill
  • 误读了,锯边,没有在手机上阅读
  • 如果AbortController 不可用,那么,明智地使用Promise.race(),您应该能够为自己设计一个可中止的Promise。它与将{signal} 传递给fetch() 的行为不同,但应用程序代码中的净效应是相同的。
  • @Roamer AbortController 的目标是向 fetch API 提供可取消的请求,这种设计原本就相当复杂;能够停止长时间运行的请求(例如在 MDN 的情况下,视频)。赛车承诺不会帮助中止任何事情。即使他们要求停止下载,您的用户仍将下载整个文件。但是,至少从 XHR2 开始,取消请求是可行的。因此,如果您需要对其进行 polyfill,您只需要返回使用 XHR 并 Promisify 它(需要注意的是,应在请求开始时声明消费者)。

标签: javascript promise fetch


【解决方案1】:

不确定我是否清楚,但据我了解,您的情况并没有什么不同。

基本相同,将控制器存储在您的逻辑可访问的位置,可能会取消它,如果需要,在发送新请求之前取消它:

let aborter = null; // make the aborter accessible
function getData(param) {
  // cancel pending request if any
  if(aborter) aborter.abort();
  // make our request cancellable
  aborter = new AbortController();
  const signal = aborter.signal;
  const url = 'https://upload.wikimedia.org/wikipedia/commons/4/47/PNG_transparency_demonstration_1.png?rand=' + param;
  return fetch(url, {signal})
  // clean up, not really needed but may help to know if there is a pending request
  .then(r => {aborter = null; return r;})
}
// first request will get aborted
getData("foo")
  .then(r => console.log('foo done'))
  .catch(e => console.error('foo failed', e.name, e.message));
// will abort the previous one
getData("bar")
  .then(r =>  console.log('bar done'))
  .catch(e => console.error('bar failed', e.name, e.message))

【讨论】:

猜你喜欢
  • 2011-05-09
  • 1970-01-01
  • 2017-12-06
  • 1970-01-01
  • 2017-06-19
  • 2014-08-12
  • 2020-10-26
  • 1970-01-01
  • 2012-07-26
相关资源
最近更新 更多