Pergunta

I am taking a look at Node.js' async module to solve an issue. I have implemented a little test:

var async = require("async");

function print(val) {
    console.log(val);
}

async.parallel([
    function(cb){ print(1); cb(null); },
    function(cb){ print(2); cb(null); },
    function(cb){ print(3); cb(null); },
    function(cb){ print(4); cb(null); },
    function(cb){ print(5); cb(null); }
],
    function(err) {
        if ( err ) {
            console.error(err);
            return;
        }
        console.log("Done!");
    }
);

console.log("Trulu");

Can I be sure that the Trulu log call will never be called before the call to async.parallel is finished? In other words, are all the functions and the final callback called before the Trulu log is called for sure?

Foi útil?

Solução

Can I be sure that the Trulu log call will never be called before the call to async.parallel is finished?

The call itself, yes.

In other words, are all the functions

I guess so, though the docs don't mention it. I would however expect no changes, since that is likely to break existing code.

and the final callback called before the Trulu log is called for sure?

No. You don't know the functions, and when they are asynchronous then the final callback will execute after Trulu. If all the functions are synchronous, you shouldn't use async anyway. Indeed, while async.js does use setImmediate internally so some callbacks (unfortunately hard to identify) will be "asynchronified", yet the maintainer stated:

Yes, making functions asynchronous is left up to the developer

If you want to ensure that callbacks are always called asynchronously (after Trulu), even when the functions are synchronous, you might consider using A+ compliant Promises.

Outras dicas

Short answer: No they are asynchronous.

Long answer:

As soon as you do anything asynchronous, inside the parralel callbacks, you can expect Trulu to get called immediatly after. When you call cb, it announce that the function returned. When all function have returned it will call the last callback.

So for that reason, if you do a setTimeout without a time and each functions are returning without anything asynchrone, they might behave as synchronous because Javascript only runs one unit at a time. And since they are probably started in order, it will look as if it run synchronously.

Take this as an example:

var looping = true;

setTimeout(function () {looping = false;}, 1000);

while(looping) {
   ...
}

This code will never leave as setTimeout will never get triggered. In async.parralel, I'm almost certain that each callbacks are going to get executed after the current unit is finished running. Which means, that you'll always have your console.log("Trulu") executed before any of the callbacks inside async.parralel.

Note

If you're looking for to do synchronous things, you shouldn't use a module called async. It's quite obvious that it's going to be asynchronous.

That said, I feel that there is a big misunderstanding with the term async. Asynchronous isn't a synonym for parralelism or having things simultaneous. Asynchrone, just means "without order in time". It could be simultaneous but it could be also sequential. To run asynchronous code on Javascript, you have to rely on an event loop.

The event loop can only process one event at a time, setTimeout is just putting the event on the loop. As soon as an event handler leaves, it gets to the next event and so on.

In your case, since you're not calling cb inside an event handler, they will be called synchronously as they never leave the current event.

Since you're using async already, async has a series call. I think this may be what you're looking for, but a warning, this is ugly (because in my opinion async.js inherently makes for a mess):

async.series([
  parallel,
  function(callBack){ console.log("Trulu"); callBack(null); }
]);

function parallel(callBack){

  async.parallel([
    function(cb){ print(1); cb(null); },
    function(cb){ print(2); cb(null); },
    function(cb){ print(3); cb(null); },
    function(cb){ print(4); cb(null); },
    function(cb){ print(5); cb(null); }
  ],
    function(err) {
        if ( err ) {
            console.error(err);
            return;
        }
        console.log("Done!");
        callBack(null);
    }
  );
}

Honestly, I think the async module in general is making javascript so much more complicated than it is natively. If you'd like an answer that shows how to do what you want to do without using the async module at all, please let me know!

Another simpler solution would be to build that last call you want to execute after built into the callback of your async.parallel:

async.parallel([
  function(cb){ print(1); cb(null); },
  function(cb){ print(2); cb(null); },
  function(cb){ print(3); cb(null); },
  function(cb){ print(4); cb(null); },
  function(cb){ print(5); cb(null); }
],
  function(err) {          
      if ( err ) {
          console.error(err);
          return;
      }
      console.log("Done!");          
      console.log("Trulu"); // Executes after all your "parallel calls" are done
  }
);
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top