Nearpoint
Nearpoint

Reputation: 7362

How do I make this Node.js program asynchronous?

In the javascript program below (Euler problem 5) I am practicing writing asynchronous / non blocking function. The program is trying to find the smallest number evenly divisible by numbers 1-10. 2520 is the first smallest and that is where the program should stop.

I set up the program so that if the functions run together, then the second checkNum should be done first and print the second one first, then the first one, but that is not happening?

How can I get the function to run at the same time, instead of one after another? I am expecting the callback from the second checkNum function I call to be called first (since it starts closer to the answer), then the first, but that is not what happens. Thanks so much!

var divides = function(a, b) {
  return b % a == 0;
 };

function checkNum(counter, callback) {
   var noRemainder = 0;
   var forward = true;
    while (forward)
    {
    for (var i = 1; i <= 10; i++) {
         if (divides(i, counter))
          { noRemainder++; }
     }

    if (noRemainder == 10) {
       console.log(counter);
       forward = false;
       callback(counter);
    } else {
      console.log(noRemainder);
      noRemainder = 0;
      counter++;
      console.log(counter);
    }
  }
}

checkNum(1, function(counter) {
             setTimeout(function(){
                        console.log("The counter is: " + counter)},3000) 
              }
);

checkNum(2500, function(counter) {
               setTimeout(function(){
                          console.log("The counter2 is: " + counter) },3000)       

                }
);

Upvotes: 0

Views: 247

Answers (3)

josh3736
josh3736

Reputation: 144912

Because checkNum is a purely CPU-bound function – that is, the only thing it does is perform computation in a tight loop – there is no reason to make it asynchronous. The function is by definition synchronous; control does not return to the caller until computations complete. Consider the following async style:

checkNum(n, function(err, result) {
    console.log(result);
});
console.log('Next line');

...and synchronous style:

console.log( checkNum(n) );
console.log('Next line');

In both cases, the result of checkNum will be printed before "Next line". Even in the async style, control is not returned until after checkNum invokes its callback and the callback completes. (Compare this to truly asynchronous functions where "Next line" would get printed before the callback gets a result.)

The real magic of node comes from the fact that most expensive operations (like I/O) are performed on a separate thread by native code, and when they're done, they invoke a JavaScript callback on the main thread. As a result, very little time is spent executing JavaScript, so your application performs exceptionally well.

However, if you find yourself writing expensive loops and calculations like this in JavaScript, you have to remember that you'll be blocking everything for the amount of time your function runs. Things happening on other threads will queue up and your application code will not have a chance to do anything until the expensive function returns.

There are several ways to work around this limitation, in order of performance:

  • Break the calculations up into chunks and use nextTick to start the processing on each chunk. This allows any queued events to process between chunks.
  • Move your calculation function into a separate file, and start up a new process to actually do the calculation. This leaves your main app free to run normally while it waits for a result. You'll want to use fork to do this since it comes with built-in IPC. Here's an example fibonacci calculator. Keep in mind this does come with overhead: it takes ~30ms and at least 10 MB of RAM to start a new node process.
  • Actually run your JavaScript code on a separate thread. Note that code will run isolated from the rest of your app; your thread will not have access to any variables from the main app. This is very similar to the process-forking approach, but is faster because you avoid the overhead of spawning a new process.
  • Do your calculations in native (C++) code, where you're free to do it on a separate thread. Here's a native fibonacci example.

Upvotes: 2

Kevin Reilly
Kevin Reilly

Reputation: 6252

You may want to give the core cluster module a try which will allow you to run a node process per core. It may work with a single core, but multiple cores is highly recommended for this approach.

Another thing to check out is the async module with the parallel control flow, though this is still applicable to the notion of the single thread.

Upvotes: 0

David W
David W

Reputation: 10184

You cannot have the functions run truly simultaneously, as if you had multiple threads running in parallel. This is because Javascript is single threaded, not multithreaded. The best you really get is "sorta kinda" parallel operation that really, in practice, isn't parallel.

Upvotes: 0

Related Questions