6

Im pretty new to node.js, so i'm wondering how to know when all elements are processed in lets say:

["one", "two", "three"].forEach(function(item){
    processItem(item, function(result){
        console.log(result);
    });
});

...now if i want to do something that can only be done when all items are processed, how would i do that?

BadKnees
  • 149
  • 1
  • 1
  • 6

3 Answers3

6

You can use async module. Simple example: The

async.map(['one','two','three'], processItem, function(err, results){
    // results[0] -> processItem('one');
    // results[1] -> processItem('two');
    // results[2] -> processItem('three');
});

The callback function of async.map will when all items are processed. However, in processItem you should be careful, processItem should be something like this:

processItem(item, callback){
   // database call or something:
   db.call(myquery, function(){
       callback(); // Call when async event is complete!
   });
}
Mustafa
  • 10,013
  • 10
  • 70
  • 116
  • Interesting, how about when it is on several levels. If processItem also calls a async function like saving to a database – BadKnees May 27 '12 at 20:40
  • My example just illustrates that, this module is meant to be used by asnychronous function calls, like database ops. If it is sequential, you won't use that. – Mustafa May 27 '12 at 20:54
  • sorry, i read the post on an iPad and missed the latter part. Thanks, that looks like the right solution – BadKnees May 27 '12 at 22:56
  • callback() is called after each processItem() completes. How do you know when *all* items in map have been processed? It is hard to understand how **async module** works. – Ed of the Mountain Apr 24 '18 at 20:46
1

forEach is blocking, see this post:

JavaScript, Node.js: is Array.forEach asynchronous?

so to call a function when all items are done processing, it can be done inline:

["one", "two", "three"].forEach(function(item){
    processItem(item, function(result){
        console.log(result);
    });
});
console.log('finished');

if there is a high io-bound load for each item to be processed, then take a look at the module Mustafa recommends. there is also a pattern referenced in the post linked above.

Community
  • 1
  • 1
silijon
  • 922
  • 1
  • 8
  • 19
1

Albeit other answers are correct, since node.js supports ES6 henceforth, in my opinion using built-in Promise library will be more stable and tidy.

You don't even need to require something, Ecma took the Promises/A+ library and implemented it to the native Javascript.

Promise.all(["one", "two","three"].map(processItem))
  .then(function (results) {
    //  here we got the results in the same order of array
} .catch(function (err) {
    //  do something with error if your function throws
}

As Javascript is a adequately problematic language (dynamic typing, asynchronous flow) when it comes to debugging, sticking with promises instead of callbacks will save your time at the end.

Buğra Ekuklu
  • 3,049
  • 2
  • 17
  • 28