简体   繁体   English

从浏览器中的 express 获取块响应

[英]Get a response in chunks from express in browser

I'm building a progress bar for some long-running server-side tasks (up to a few minutes), and I'd like a way to display the progress of the task.我正在为一些长时间运行的服务器端任务(最多几分钟)构建一个进度条,我想要一种显示任务进度的方法。 I could use WebSockets or poll on intervals, but I don't want to keep track of each task.我可以使用 WebSockets 或间隔轮询,但我不想跟踪每个任务。 Instead, I'd like to use long-polling and write progress updates to the stream.相反,我想使用长轮询并将进度更新写入流。

Here is a demo of what the route should look like on the server这是路由在服务器上应该是什么样子的演示

app.get('/test', (req, res) => {
    let num = 0;
    const interval = setInterval(() => res.write(num++ + ' '), 300);
    setTimeout(() => {
        clearInterval(interval);
        res.send();
    }, 5000);
});

Doing cURL on that endpoint with -N works perfectly, however, I'm having some issues when it comes to implementing this in the browser.使用-N在该端点上执行 cURL 效果很好,但是,在浏览器中实现此功能时遇到了一些问题。

I tried with fetch like this:我试过这样取:

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));
}

This worked just dandy on Chrome, but not on firefox and as you can see, it's not supported here:这在 Chrome 上很有效,但在 Firefox 上无效,如您所见,此处不支持:

https://caniuse.com/mdn-api_windoworworkerglobalscope_fetch_streaming_response_body https://caniuse.com/mdn-api_windoworworkerglobalscope_fetch_streaming_response_body

However, I tried a different approach, this time with XHR但是,我尝试了不同的方法,这次使用 XHR

const xhr = new XMLHttpRequest()
xhr.open("GET", url)
xhr.onprogress = function () {
    console.log(xhr.responseText);
};
xhr.send();

This works perfectly in Firefox, but in Chrome, the onProgress event only fires after the entire request has been processed.这在 Firefox 中非常有效,但在 Chrome 中,onProgress 事件仅在处理完整个请求后才会触发。 I've also tried with onReadyStateChange , but that results in the same problem.我也试过onReadyStateChange ,但这会导致同样的问题。

>_< How do I read this gosh darn data in chunks as it updates in either browser? >_<当它在任一浏览器中更新时,我如何以块的形式读取这个该死的数据? I guess I could try Axios, but do I really need this?我想我可以试试 Axios,但我真的需要这个吗?

EDIT: One thing it might be worth mentoining is that Chrome and Firefox seem to handle the fetch behavior differently.编辑:值得一提的一件事是 Chrome 和 Firefox 似乎以不同的方式处理获取行为。 With Chrome, I can work with the fetch object before the fetch completes, so I do使用 Chrome,我可以在 fetch 完成之前使用 fetch 对象,所以我这样做

const response = await fetch(url);
console.log("Preflight complete, fetch is not done though");

but in Firefox, the console log won't execute until the fetch resolves.但在 Firefox 中,控制台日志在获取解决之前不会执行。 This is why I think I can't work with the response body in Firefox, but I can with Chrome.这就是为什么我认为我无法使用 Firefox 中的响应正文,但我可以使用 Chrome。

According to this GitHub issue:根据这个 GitHub 问题:

https://github.com/ratpack/ratpack/issues/443#issuecomment-59621215 https://github.com/ratpack/ratpack/issues/443#issuecomment-59621215

This is a Chrome/Webkit bug.这是一个 Chrome/Webkit 错误。 Changing the Content-Type of the request from anything other than text/plain makes it work with XHR on Chrome.text/plain以外的任何Content-Type更改请求的Content-Type使其在 Chrome 上与XHR使用。 So if I change the server response to因此,如果我将服务器响应更改为

app.get('/test', (req, res) => {
    let num = 0;
    let interval = setInterval(() => res.write(num++ + ' '), 300);
    // THIS IS A DUMB HACK TO GET CHROME TO PLAY NICE X_X
    res.setHeader('Content-Type', 'text/html');
    setTimeout(() => {
        clearInterval(interval);
        res.send();
    }, 5000);
});

SHOCKINGLY, this also seems to fix the issue with fetch streaming in Firefox with unmodified flags.令人震惊的是,这似乎也解决了在 Firefox 中使用未修改标志获取流的问题。 I think I'll go with the XHR method for now, just because it's a bit more compaitble, HOWEVER, the fetch version is significanlty easier to work with given each new chunk is processed individually.我想我现在会使用XHR方法,只是因为它更兼容一点,但是,鉴于每个新块都是单独处理的,获取版本更容易使用。

AHHHHHHHHH啊啊啊啊啊

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM