暂停 HTTP fetch() 请求

Pause HTTP fetch() requests

提问人:brillout 提问时间:2/19/2023 更新时间:2/28/2023 访问量:678

问:

正如 Stack Overflow - How do I cancel an HTTP fetch() request?中看到的,我们现在可以使用 AbortController 中止请求。fetch()

我不想中止请求,只想暂停它,稍后再恢复。可能吗?fetch()

javascript ajax fetch-api http-streaming

评论

4赞 Harlan Wei 2/19/2023
暂停应该有什么影响?例如,如果当请求已发送到远程服务器但客户端尚未收到响应时暂停,则当客户端收到响应时,浏览器应该怎么做?它是否应该将响应保留在内存中并等待调用触发事件?如果在发送请求期间暂停怎么办?暂停 a 的语义对我来说不是很清楚。fetchcontinuefetchfetch
1赞 Oskar Grosser 2/19/2023
您是否正在寻找范围请求或类似请求?也许这篇关于流式处理请求的文章会有所帮助。或者,您可以将某些内容与 XHR 的进度事件拼接在一起。
0赞 epascarello 2/21/2023
那么你期待什么?人们问你问题,你没有回应。暂停有什么作用?用例到底是什么?
0赞 brillout 2/22/2023
总的来说,我很好奇,我脑海中有很多不同的用例。也就是说,主要用例是一些具有最高优先级的事件,所有其他待处理请求都应暂停。紧急请求完成后,其他请求应恢复。
0赞 brillout 2/22/2023
很抱歉没有回复,并感谢到目前为止的回答。如果暂停是可能的(我想知道服务器如何处理建议的答案),我很惊讶暂停不是一种常见的做法。

答:

2赞 xdumaine 2/22/2023 #1

要回答问题的根源,请执行以下操作:

我不想中止 fetch() 请求,而只想暂停它并稍后恢复它。可能吗?

答案是“不,这是不可能的”。

也就是说,要回答您的评论:

主要用例是一些具有最高优先级的事件,所有其他待处理请求都应暂停。紧急请求完成后,其他请求应恢复。

您可以实现类似优先级队列之类的东西(手动或通过某些现有库,这超出了本文的范围),以便您的应用程序在处理任何更高优先级的结果后处理已完成的承诺的结果。fetch

评论

0赞 brillout 2/22/2023
暂停的动机是所有待处理的 HTTP 请求都已被触发:它们应该暂停,以便从根本上增加具有更高/最高优先级的新请求的“网络优先级”。现在,这种最高优先级的请求可能随时发生,而且发生的时间是不可预测的,这意味着优先级队列无济于事。顺便说一句,如果浏览器会缓存已经收到的块,中止而不是暂停同样有效,但我认为浏览器(不能)这样做。
1赞 Surya R 2/23/2023 #2

实际上,除了 AbortController 之外,其他 js 方法都无法暂停和恢复 HTTP 请求,

i) 我们可以在 promise 中使用 fetch() 调用,我们实际上可以决定是拒绝还是解决请求,是要暂停还是拒绝请求。这将不支持恢复功能。

ii) AbortController 执行类似的功能,即暂停请求(中止正在进行的请求),并在使用相同的控制器时再次发出请求

const controller = new AbortController();
const signal = controller.signal;    
fetch(url, {..., signal: signal}).then(response => ...);

暂停 :

controller.abort() 

恢复:基本上,我们再次使用相同的控制器对象 fetch 再发出一个请求。fetch(url, {..., signal: signal}).then(response => ...);

更多数据请参考这里:https://developer.mozilla.org/en-US/docs/Web/API/AbortController

iii)如果您正在寻找通过HTTP发生的流进程暂停/恢复,则可以使用我在此处找到的以下示例方法: https://gist.github.com/Grigore147/4611134

var Http = require('http');
var Fs   = require('fs');

// some url to big video file
var url = 'url';
var path = 'save_path';

var downloaded = 0;
var percents = 0;
var size = 0;

var request = Http.request(url, function(response) {
  size = parseInt(response.headers['content-length']);
  
  response.on('data', function(chunk) {
    downloaded += chunk.length;
    percents = parseInt((downloaded / size) * 100);
    
    console.log(percents +'%', downloaded +'/'+size);
  });
  
  response.on('error', function(error) {
    console.log(error);
  });
  
  response.pipe(Fs.createWriteStream(path));
  
  setTimeout(function() {
    response.pause(); console.log('stream paused');
    
    setTimeout(function() {
      response.resume(); console.log('stream resumed');
    }, 5000);
  }, 5000);
}).end();
1赞 Unamata Sanatarai 2/24/2023 #3

无法暂停 .是要取消的,而不是暂停的。而且由于它将取消,因此无法恢复。这就像把刀放在一根绳子上。 在这个类比中。fetch()AbortControllerCancel == cut

因此,您可以考虑几种方法。

  1. 将一个大请求拆分为多个小请求
  2. 应用标头以接收多个部分,但随后必须自己加入它们,并且必须支持标头。Range
  3. 也许您可以阅读 ReadableStream 以及它是否可以在此处应用(长镜头)
  4. https://stackoverflow.com/a/75537289/2119863 看起来也很有前途;)