0

I have a code snippet in nodejs like this:

in every 2 sec, foo() will be called.

function foo() 
{
    while (count < 10) 
    {
        doSometing()
        count ++;``
     }
}

doSomething()
{
   ...
}

The limitation is, foo() has no callback. How to make while loop execute and foo() completes without waiting for dosomething() to complete (call dosomething() and proceed), and dosomething() executes parallely?

nebi
  • 727
  • 3
  • 9
  • 24

1 Answers1

0

I think, what you want is:

function foo() 
{
    while (count < 10) 
    {
        process.nextTick(doSometing);
        count ++;
     }
}

process.nextTick will schedule the execution of doSometing on the next tick of the event loop. So, instead of switching immediately to doSometing this code will just schedule the execution and complete foo first.

You may also try setTimeout(doSometing,0) and setImmediate(doSometing). They'll allow I/O calls to occur before doSometing will be executed.

Passing arguments to doSomething

If you want to pass some parameters to doSomething, then it's best to ensure they'll be encapsulated and won't change before doSomething will be executed:

setTimeout(doSometing.bind(null,foo,bar),0);

In this case doSometing will be called with correct arguments even if foo and bar will be changed or deleted. But this won't work in case if foo is an object and you changes one of its properties.

What the alternatives are?

If you want doSomething to be executed in parallel (not just asynchronous, but actually in parallel), then you may be interested in some job-processing solution. I recommend you to look at kickq:

var kickq = require('kickq');

kickq.process('some_job', function (jobItem, data, cb) {
  doSomething(data);
  cb();
});

// ...

function foo() 
{
    while (count < 10) 
    {
        kickq.create('some_job', data);
        count ++;
     }
}

kickq.process will create a separate process for processing your jobs. So, kickq.create will just register the job to be processed.

kickq uses redis to queue jobs and it won't work without it.

Using node.js build-in modules

Another alternative is building your own job-processor using Child Process. The resulting code may look something like this:

var fork = require('child_process').fork,
    child = fork(__dirname + '/do-something.js');

// ...

function foo() 
{
    while (count < 10) 
    {
        child.send(data);
        count ++;
     }
}

do-something.js here is a separate .js file with doSomething logic:

process.on('message', doSomething);

The actual code may be more complicated.

Things you should be aware of

Node.js is single-threaded, so it executes only one function at a time. It also can't utilize more then one CPU.

Node.js is asynchronous, so it's capable of processing multiple functions at once by switching between them. It's really efficient when dealing with functions with lots of I/O calls, because it's newer blocks. So, when one function waits for the response from DB, another function is executed. But node.js is not a good choice for blocking tasks with heavy CPU utilization.

It's possible to do real parallel calculations in node.js using modules like child_process and cluster. child_process allows you to start a new node.js process. It also creates a communication channel between parent and child processes. Cluster allows you to run a cluster of identical processes. It's really handy when you're dealing with http requests, because cluster can distribute them randomly between workers. So, it's possible to create a cluster of workers processing your data in parallel, though generally node.js is single-threaded.

Leonid Beschastny
  • 50,364
  • 10
  • 118
  • 122
  • @Lenoid I know process.nextTick() will work. But nextTick() executes queued event before any I/O. see here: http://stackoverflow.com/questions/16220710/understanding-the-node-js-event-queue-and-process-nexttick. Here foo() is a I/O call and I wanted to doSomething() to get executed in background and next foo() starts execution. But nextTick() will make all the queued doSomething() to get executed, before starting next foo(). – nebi Jul 25 '13 at 05:18
  • Use `setTimeout` then. It won't block `I/O` operations. – Leonid Beschastny Jul 25 '13 at 06:20
  • @ Leonid Probably that can help – nebi Jul 25 '13 at 15:29
  • There is no other buld-in way do do so, except for executing `doSometing` in separate process with `child_process`. You may be also interested in some job-processing tool, like [kickq](https://github.com/verbling/kickq). I may add examples for both solutions, if you want. – Leonid Beschastny Jul 25 '13 at 15:33
  • @ Leonid **setTimeout**, it appear to put function call in some queue and execute one by one after time interval expires. Now if the function is modifying a variable then every function gets modified value of that variable( modified by previous call). What if **doSomething** should works as thread, which means each call will have original variable, not the modified one by the previous call. Yes like as u suggested **child_process** . If u can provide some example for the other ways which u discussed in ur earlier comment, it would be gud. thnx. – nebi Jul 26 '13 at 09:38
  • @ Leonid Its really informative. How does **setTimeout** function execution go? Does the execution of **doSomething** goes parallely. I mean , let us suppose , while loop runs for forever like this ` while(1)` then how will the execution go, after the time interval for **setTimeout** expires ? In multiprocessor CPU will it be scheduled on another CPU ? And what would happen if the cpu is single processor ? Can u comment on this? And also refer some good resource to me to look for cool programming languages like js, node, ruby or any web development framework if u know. – nebi Jul 26 '13 at 20:06
  • As for web development frameworks, I'm generally work with `node.js` and `clojure`, so I can't say a lot about other languages. There are lots of frameworks for `node.js` for different tasks. If you want to build a web application with `node.js` you'll definitely need [express.js](http://expressjs.com/). As for other frameworks... can you tell me more about what you want to build with `node.js`? – Leonid Beschastny Jul 26 '13 at 21:04
  • @ Leonid I want to build complete website, I want to have complete knowledge of the framework. It's like to do a project which expose me to a decent web framework completely. How can I start ? – nebi Jul 27 '13 at 11:06
  • I think you should start from some example. Check [this project on github](https://github.com/madhums/node-express-mongoose-demo). It combines in one example all most popular `node.js` modules: `expless.js`, `mongoose.js`, `passport.js`, `jade`. – Leonid Beschastny Jul 30 '13 at 11:47