Why is Node JS blocking async file operation?

I was under the impression that although Node JS is single threaded, the io file was asynchronous.

var express = require('express');
var http = require('http');
var fs = require('fs');
var app = express();

var server = app.listen(1337, function() {
    console.log('Listening on port %d', server.address().port);
});

app.get('/home', function(req, res){
  console.log("/home")

  res.sendFile('C:\\Users\\Owner\\AppData\\Roaming\\npm\\test.html');
  //var file = fs.createReadStream('C:/Users/Owner/AppData/Roaming/npm/test.html');
  //file.on("open", function(){
  //   file.pipe(res);
  //});
});

app.get('/home2', function(req, res){
  console.log("/home2")

  res.sendFile('C:\\Users\\Owner\\AppData\\Roaming\\npm\\test2.html');
  //var file = fs.createReadStream('C:/Users/Owner/AppData/Roaming/npm/test.html');
  //file.on("open", function(){
  //   file.pipe(res);
  //});
});

app.get('/music', function(req, res){
  console.log("/music")
  //res.sendFile('C:\\Users\\Owner\\AppData\\Roaming\\npm\\01 Give Life Back To Music.mp4');
  var readStream = fs.createReadStream('C:\\Users\\Owner\\AppData\\Roaming\\npm\\01 Give Life Back To Music.mp4');
  console.log("/afterRead");
  readStream.on('data', function(data) {
        var flushed = res.write(data);
        // Pause the read stream when the write stream gets saturated
        console.log( 'streaming data' );
        if(!flushed){
            readStream.pause();
        }
    });

    res.on('drain', function() {
        // Resume the read stream when the write stream gets hungry 
        readStream.resume();
    });

  readStream.on('end', function () {
    res.end();
    console.log('end');
  });
});

app.get('/music2', function(req, res){
  console.log("/music2")
  //res.sendFile('C:\\Users\\Owner\\AppData\\Roaming\\npm\\01 Give Life Back To Music.mp4');
  var readStream = fs.createReadStream('C:\\Users\\Owner\\AppData\\Roaming\\npm\\01 Give Life Back To Music.mp4');
  console.log("/afterRead");
  readStream.on('data', function(data) {
        var flushed = res.write(data);
        // Pause the read stream when the write stream gets saturated
        console.log( 'streaming data' );
        if(!flushed){
            readStream.pause();
        }
    });

    res.on('drain', function() {
        // Resume the read stream when the write stream gets hungry 
        readStream.resume();
    });

  readStream.on('end', function () {
    res.end();
    console.log('end');
  });
});

      

Above is the server code, here is my HTML:

<html>
    <script>

    </script>
    <body>
        <video width="320" height="240" controls>
          <source src="http://localhost:1337/music1" type="video/mp4">
          Your browser does not support the video tag.
        </video>
    </body>
    </html>

<html>
<script>

</script>
<body>
    <video width="320" height="240" controls>
      <source src="http://localhost:1337/music2" type="video/mp4">
      Your browser does not support the video tag.
    </video>
</body>
</html>

      

I expected to be able to call localhost: 1337 / music more than once, but when I call localhost: 1337 / home on two tabs in Google Chrome (or Firefox or Internet Explorer 11), the second page does not load audio until all bytes will not be transferred for the first request to localhost: 1337 / music. The code is asynchronous and I know it is not blocking because if it blocks, the second request ... / home 2 should not serve the file.

Does anyone know why the async code is blocking? I checked through the developer tools in Chrome that / music and / music2 are being called (from a browser perspective). I also ran into the same problem not using Express, so I'm pretty sure it's not a framework.

  • Also, I have console logging. When the second page loads, I see a second / home and some "streaming" in the console, because it is streaming for the first page. Chrome says that the request for music came out, but the console doesn't print anything, implying that the function hasn't completed yet - implying that something else is blocking it.
+3


source to share


3 answers


Chrome will only download one copy of the file at a time (i.e. if you download a really large file, subsequent requests for the same file are queued, even through tabs). The development environment says the request is pending, but pending actions are indeed a limitation for Chrome, not Node JS server. The file upload is specifically tied to the url as a key, so I could have different urls to download the same file, and also why I could make other requests to the server while the file was being downloaded.



+2


source


You may have encountered the connection limit with your browser. Try increasing the limit (if you can, I think you can do it in Firefox at least) and try again.

Alternatively, you can simply pass the file in response instead of manually listening for "data" and "end". For example:



app.get('/music2', function(req, res){
  console.log("/music2")
  //res.sendFile('C:\\Users\\Owner\\AppData\\Roaming\\npm\\01 Give Life Back To Music.mp4');
  var readStream = fs.createReadStream('C:\\Users\\Owner\\AppData\\Roaming\\npm\\01 Give Life Back To Music.mp4');
  console.log("/afterRead");
  readStream.pipe(res);
});

      

-1


source


It seems that createReadStream is blocking the file. I have tried this code

var http = require('http');
var fs = require('fs');
var qs = require('querystring');

http.createServer(function (req, res) {
    var str = req.url.split('?')[1];
    var query = qs.parse(str);

    var readStream = fs.createReadStream('./response' + (query.q || '') + '.json');
    readStream.on('data', function(data) {
        var flushed = res.write(data);
        console.log( 'streaming data' );
        if(!flushed){
            readStream.pause();
        }
    });

    res.on('drain', function() {
        readStream.resume();
    });
}).listen(1337, '127.0.0.1');

      

and opened two tabs with localhost

and localhost/?q=1

and it read two separate files fine, but if you try to read one file by two processes, the second request hangs.

-1


source







All Articles