1

I have an Express.js server with a route that is responsible for parsing and importing a CSV file.

I'd like to report the status of the import process in realtime back to the user's browser.

Streaming responses from Express.js is straight forward:

router.get( '/test', function( _req, _res, _next ) {
    _res.write( 'File import initiated.' );

    // ... processing CSV in loop

    _res.write( 'Processing row x.' );

    // artificial delay to simulate some i/o
    setTimeout( function() {
        _res.write( 'File import completed successfully.' );
        _res.end();
    }, 2000 )
} );

Sending a HTTP request to the endpoint via CURL works as expected. In the above example two streamed responses are received immediately, followed by the final response after two seconds.

This is not the case in the browser (Chrome) however. Testing both with jQuery $.ajax, and a raw XHR call, the entire response appears to be buffered and returned all at once when the response is complete.

How is this type of communication normally handled? I assume socket.io is an option, but surely there's a simpler way to utalise the build int XHR or XHR2 features of the browser?

Matt Stone
  • 3,705
  • 4
  • 23
  • 40
  • 1
    Do not believe process is currently possible using `XHR` alone using a single request, though should be possible using multiple requests. See http://stackoverflow.com/questions/35899536/method-for-streaming-data-from-browser-to-server-via-http/. – guest271314 Jun 28 '16 at 06:33
  • See also https://github.com/yutakahirano/fetch-with-streams/issues/30. You could request from server until total bytes of file have been received, then re-assemble file client-side. – guest271314 Jun 28 '16 at 06:42
  • https://jakearchibald.com/2016/streams-ftw/#streams-the-fetch-api , http://jsbin.com/vuqasa/edit?js,console – guest271314 Jun 28 '16 at 06:51
  • thank you for the links @guest271314 - these all indicate that streaming over XHR is not currently feasible – Matt Stone Jun 29 '16 at 09:22

1 Answers1

2

You can give back a reference id to the client, and the client calls the correct http api's to gather the status of that csv processing request. You might want some backend support to enable this. Something like some tables in the database that can track this status.

router.get( '/test', function( _req, _res, _next ) {
    SaveFile(_res.file).then(function(id) {
        _res.end(JSON.stringify({id: id});
    });
});

router.get( '/status', function( _req, _res, _next ) {
    GetStatus(_res.params.id).then(function(status) {
        _res.end(JSON.stringify(status));
    });
});

Else, if you still want realtime, employ websockets. You've to design the form of communication you expect.

deostroll
  • 11,661
  • 21
  • 90
  • 161