As I work on creating a progress bar to track long-running server-side tasks that may take up to a few minutes, I am exploring different methods to display the progress of each task. While WebSockets and interval polling are options, I prefer using long-polling to write progress updates directly to the stream without having to individually track each task.
To give you an idea of what the server route should look like, here is a demo:
app.get('/test', (req, res) => {
let num = 0;
const interval = setInterval(() => res.write(num++ + ' '), 300);
setTimeout(() => {
clearInterval(interval);
res.send();
}, 5000);
});
cURL works smoothly when used with the -N
flag on this endpoint. However, I encountered some challenges while attempting to implement this functionality in the browser.
I initially tried using fetch in the following manner:
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 method worked well in Chrome but faced compatibility issues in Firefox as highlighted here.
As an alternative, I experimented with XHR:
const xhr = new XMLHttpRequest()
xhr.open("GET", url)
xhr.onprogress = function () {
console.log(xhr.responseText);
};
xhr.send();
While this approach performed effectively in Firefox, Chrome's onProgress event only triggered once the entire request was processed. Attempts with onReadyStateChange
yielded similar results.
>_< How can I retrieve data in chunks as it updates in both browsers? Should I consider using Axios?
EDIT: It is noteworthy that Chrome and Firefox handle fetch behavior differently. In Chrome, I can manipulate the fetch object before completion, which is not the case in Firefox. This distinction impacts my ability to interact with the response body accordingly.