buaaji
buaaji

Reputation: 121

How to make node works concurrently?

Node.js is famous for concurrency, however, I'm confused by how to make it work concurrently. I started two requests from Chrome one by one very quickly, and I Expected the outputs in console should be:

  1. "get a new request"
  2. immediately after my second request, "get a new request" should be printed
  3. after several seconds, "end the new request"
  4. after several seconds, "end the new request"

However, what I saw is:

  1. "get a new request"
  2. after several seconds, "end the new request"
  3. "get a new request"
  4. after several seconds, end the new request

That means the second request is NOT handled until the first one is done. Below is my sample code, anything I missed?

   var http = require("http");
   var url = require("url");

   function start(route) {
    http.createServer(function(request, response) {
      console.log('get a new request');

      // a time consuming loop           
      for (var i=0; i<10000000000; ++i) {
      }

      route(url.parse(request.url).pathname);
      response.writeHead(200, {"Content-Type": "text/plain"});
      response.end();
      console.log('end the new request');
    }).listen(5858);
   }

   function saySomething(something)  {
     console.log(something);
   }

   exports.start = start;
   exports.saySomething = saySomething;

Upvotes: 2

Views: 192

Answers (4)

GiveMeAllYourCats
GiveMeAllYourCats

Reputation: 888

T̶h̶i̶s̶ ̶i̶s̶ ̶t̶h̶e̶ ̶e̶x̶p̶e̶c̶t̶e̶d̶ ̶b̶e̶h̶a̶v̶i̶o̶r̶,̶ ̶w̶e̶ ̶c̶a̶l̶l̶ ̶t̶h̶i̶s̶ ̶̶b̶l̶o̶c̶k̶i̶n̶g̶̶.̶ ̶T̶h̶e̶ ̶s̶o̶l̶u̶t̶i̶o̶n̶ ̶f̶o̶r̶ ̶h̶a̶n̶d̶l̶i̶n̶g̶ ̶c̶o̶n̶c̶u̶r̶r̶e̶n̶t̶ ̶r̶e̶q̶u̶e̶s̶t̶ ̶i̶s̶ ̶m̶a̶k̶i̶n̶g̶ ̶t̶h̶e̶ ̶c̶o̶d̶e̶ ̶̶n̶o̶n̶-̶b̶l̶o̶c̶k̶i̶n̶g̶̶.̶ ̶A̶s̶ ̶s̶o̶o̶n̶ ̶a̶s̶ ̶y̶o̶u̶ ̶c̶a̶l̶l̶e̶d̶ ̶̶r̶e̶s̶p̶o̶n̶s̶e̶.̶w̶r̶i̶t̶e̶H̶e̶a̶d̶̶ ̶t̶h̶e̶ ̶c̶o̶d̶e̶ ̶b̶e̶g̶a̶n̶ ̶b̶l̶o̶c̶k̶i̶n̶g̶ ̶w̶a̶i̶t̶i̶n̶g̶ ̶f̶o̶r̶ ̶̶r̶e̶s̶p̶o̶n̶s̶e̶.̶e̶n̶d̶̶.

EDIT 7/8/14: Had to deal with this problem recently and found out you can use threads for this: https://www.npmjs.org/package/webworker-threads

Webworker-threads provides an asynchronous API for CPU-bound tasks that's missing in Node.js:

var Worker = require('webworker-threads').Worker;
require('http').createServer(function (req,res) {
  var fibo = new Worker(function() {
    function fibo (n) {
      return n > 1 ? fibo(n - 1) + fibo(n - 2) : 1;
    }
    this.onmessage = function (event) {
      postMessage(fibo(event.data));
    }
  });
  fibo.onmessage = function (event) {
    res.end('fib(40) = ' + event.data);
  };
  fibo.postMessage(40);
}).listen(port);

And it won't block the event loop because for each request, the fibo worker will run in parallel in a separate background thread.

Upvotes: -1

pbo
pbo

Reputation: 537

You don't have to do anything.

It's based on non blocking I/O. Put simply, there is an event loop. A certain set of sync code are run, once done, the next iteration is run that picks up the next set of sync code to run. Anytime an async op is run (db fetch, setTimeout, reading a file, etc) the next tick of the event loop is run. This way there is never any code just waiting.

It's not threaded. In your example, the for loop is in one continuous chunk of code, so js will run the entire for loop before it can handle another http request.

Try putting a setTimeout around the for loop so that node can switch to the next event loop and in your case handle a web request.

Upvotes: 3

vkurchatkin
vkurchatkin

Reputation: 13570

node can't handle these:

for (var i=0; i<10000000000; ++i) {}

concurrently. But it handles IO concurrently

Upvotes: 2

Related Questions