Receive a response in fragments from express on the browser

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.

Answer №1

After researching on the GitHub platform, it has been discovered that the issue at hand is related to a bug in Chrome and Webkit. To resolve this bug, it is recommended to adjust the Content-Type of the request to anything other than text/plain, which will enable compatibility with XHR in Chrome.

To implement this fix, you can modify the server response as shown below:

app.get('/test', (req, res) => {
    let num = 0;
    let interval = setInterval(() => res.write(num++ + ' '), 300);
    // Implementation to address Chrome compatibility
    res.setHeader('Content-Type', 'text/html');
    setTimeout(() => {
        clearInterval(interval);
        res.send();
    }, 5000);
});

Interestingly, this adjustment not only resolves the issue with fetch streaming in Firefox without any additional modifications, but it also makes the XHR method more compatible. However, working with the fetch version may be preferred due to its ease of processing new data chunks individually.

AHHHHHHHHH

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Using express and sequelize to load different models in a single route

In my express application, I have successfully loaded related bus, family, and person models to supply them separately to the view. Now, I am trying to load the volunteerTypes model and pass it as a separate object to the view. exports.get = (request, res ...

Repeated calls to Angular's <img [src]="getImg()"> frequently occur

Can someone help me figure out what's going on here? Recently, I set up a new Angular project and in app.component.html, I have the following code: <img [src]="getDemoImg()"> In app.component.ts: getDemoImg(){ console.log('why so m ...

Having trouble retrieving a specific key from the state object in Redux using TypeScript

I have incorporated TypeScript into my Ionic project, using React hooks. I recently added an errorReducer to handle any errors that may arise from the server. Below is a snippet of my code: Action import { ERROR_OCCURRED } from "./types"; ...

Using TypeScript, you can replace multiple values within a string

Question : var str = "I have a <animal>, a <flower>, and a <car>."; In the above string, I want to replace the placeholders with Tiger, Rose, and BMW. <animal> , <flower> and <car> Please advise on the best approach ...

What is the best way to send the output of a function once the loop has completed?

Within a Node/Express server written in CoffeeScript, I am working on a function that looks like this: @resolveServers = (url, servers, answer) -> result = [] treatServer(url, server, (treatAnswer) -> result.push(treatAnswer) ) for server ...

Creating a Node.JS Express app for authentication resulted in a TypeError

Currently, I am going through a tutorial on Node.js that starts with a basic authentication program. This is my second time following this tutorial, and the first time it worked without any issues. However, after uninstalling node and starting over (instal ...

Issue with TypeORM @BeforeInsert causing a field in Entity not to be populated with value

Currently, I am facing an issue where I am attempting to update or insert into a token field before the record is saved. However, when utilizing the @BeforeInsert hook, I encounter the following error: "error": "Cannot read property 'co ...

Troubleshooting an issue with an AJAX request

Having trouble getting the HTML back from an AJAX call - works in FF but returns "null" in IE when using alert(result.html()); Here's the code, any suggestions? Thanks! The errors variable is also null in IE. It doesn't matter what element I u ...

When should we set an expiration time for shopping carts in Mongodb?

I am currently in the process of developing an e-commerce website using ExpressJs and MongoDB, and I have encountered a challenge that I need guidance on: When should we expire the cart (remove the items from the cart and return them to inventory) from a t ...

Exploring the utilization of type (specifically typescript type) within the @ApiProperty type in Swagger

Currently, I am grappling with a dilemma. In my API documentation, I need to include a 'type' in an @ApiProperty for Swagger. Unfortunately, Swagger seems to be rejecting it and no matter how many websites I scour for solutions, I come up empty-h ...

In Javascript, you can quickly update other variables with just a one-line conditional statement

Is there a way to simplify this code into one line without using an if-else statement? For example, updating all variables when a specific condition is met? const dogStatus = present ? "bark" : "beep"; const catStatus = present ? "meow" : "meep"; const f ...

What could be the reason behind the varying outcomes browsers provide for the JavaScript expression new Date(-105998400000)?

When I use ASP.NET MVC 3 with the default Json serializer, I notice that dates from my JsonResults come back in the format /Date(-105998400000)/. To handle this, I extract the number and create a new Date object with this value. However, I am experiencing ...

Looking to modify the CSS of an element during a drop event using interact.js?

I've encountered an issue in my code where setAttribute and .transform are not working as expected. I have tried using them within the ondrop event function, but with no success. interact('.dropzone') .dropzone({ // Setting the r ...

Display the map using the fancybox feature

I have added fancybox to my view. When I try to open it, I want to display a map on it. Below is the div for fancybox: <div id="markers_map" style="display:none"> <div id="map_screen"> <div class="clear"></div> </div&g ...

Encountering issues with integrating an external plugin with AngularJS code

For my app, I am attempting to incorporate intercom for monitoring user activity. It functions correctly when placed inside a script tag in index.html. However, I encounter an error when trying to use it in a .ts file as shown below: app/components/rocket/ ...

Issue with setting headers in Express.js when using an exported function

Exploring testing methods with Express using Mocha, Chai, Chai-HTTP plugin, and MongoDB with Mongoose. One particular test is designed to check if MongoDB correctly handles errors when attempting to retrieve a document with a faulty _id value (too short). ...

WebSocket connection established on port 8888, while the web server is running on port 80 - incompatible to merge the two services

Here is some node.js server-side code that involves watching a file and sending modifications to the browser: var app = require('http').createServer(handler) , io = require('socket.io').listen(app) , fs = require('fs') a ...

Using React Native, you can easily apply styles to View components by passing them

Is it a bug? Or is the View styles props object supporting inline props as well? For example, in the traditional way and also written in React Native documentation: function App() { return ( <View style={styles.box}></View> ) } const ...

Wrap every character in a span tag within this text

Extracting search strings from an object obj[item].coveredText and replacing each character with a span is what I aim to achieve. Currently, I can only replace the entire search string with a single span element. Any suggestions would be greatly appreciat ...

Displaying [object Object] in Angular Material datatable

I am currently working on implementing a datatable component using Express and Firebase DB. Below is the service request data: getText() { return this.http.get<nomchamp[]>(this.url) .map(res => { console.log(res); return res }); ...