【发布时间】:2021-09-30 09:45:40
【问题描述】:
我正在为一些长时间运行的服务器端任务(最多几分钟)构建一个进度条,我想要一种显示任务进度的方法。我可以使用 WebSockets 或按间隔轮询,但我不想跟踪每个任务。相反,我想使用长轮询并将进度更新写入流。
这是路由在服务器上的样子的演示
app.get('/test', (req, res) => {
let num = 0;
const interval = setInterval(() => res.write(num++ + ' '), 300);
setTimeout(() => {
clearInterval(interval);
res.send();
}, 5000);
});
使用-N 在该端点上执行 cURL 效果很好,但是在浏览器中实现它时遇到了一些问题。
我尝试过这样的获取:
const response = await fetch(url);
const reader = response.body.getReader();
const decoder = new TextDecoder();
while (true) {
const { done, value } = await reader.read();
if (done)
break;
console.log(decoder.decode(value));
}
这在 Chrome 上运行得很好,但在 Firefox 上却不行,正如你所见,这里不支持它:
https://caniuse.com/mdn-api_windoworworkerglobalscope_fetch_streaming_response_body
不过,我尝试了不同的方法,这次是使用 XHR
const xhr = new XMLHttpRequest()
xhr.open("GET", url)
xhr.onprogress = function () {
console.log(xhr.responseText);
};
xhr.send();
这在 Firefox 中完美运行,但在 Chrome 中,onProgress 事件仅在整个请求被处理后才会触发。我也尝试过使用onReadyStateChange,但这会导致同样的问题。
>_ 在任一浏览器中更新时,我如何分块读取这些该死的数据?我想我可以试试 Axios,但我真的需要这个吗?
编辑:值得一提的是 Chrome 和 Firefox 似乎以不同的方式处理获取行为。使用 Chrome,我可以在 fetch 完成之前使用 fetch 对象,所以我这样做了
const response = await fetch(url);
console.log("Preflight complete, fetch is not done though");
但在 Firefox 中,控制台日志在获取解决之前不会执行。这就是为什么我认为我不能在 Firefox 中使用响应正文,但我可以使用 Chrome。
【问题讨论】:
-
奇怪 - 获取流响应正文似乎在 Firefox 90 中工作 - 不,我没有弄乱任何标志 - 根据 MDN 自 Firefox 65 以来已经这样做了 - 是什么让你认为它不起作用,你试过吗?你在firefox中遇到了什么问题
-
好吧,@Bravo,我尝试使用 fetch 示例,但它根本不起作用。 XHR 示例在 FF 中运行良好。我也尝试启用这些标志,但这对我没有任何好处,这不仅是我的浏览器需要处理的事情。
-
@Bravo 我想这取决于您所说的“工作”是什么意思。我没有像 OP 那样进行测试,但从技术上讲,在获取完成后流只触发一个事件也“工作”,因为你没有丢失任何数据。
-
@slebetman 是的,我得到了所有的数据,但是只有在服务器完成请求之后,而不是在创建请求之后的后续事件中。
-
@SethPainter - 是的,你确实说过关于 chrome 和 onprogress - 我实际上指的是获取流响应正文
标签: javascript express xmlhttprequest fetch long-polling