NodeJS, Async forEachSeries execution order
Asked Answered
Q

1

9

Just trying to get my head around using Async module for NodeJS.

I have the following code.

var a1 = [1,2,3,4,5,6,7,8];
async.forEachSeries(a1, function(n1, callback) {
    console.log(n1);
    var a2 = [10,11,12,13,14];
    async.forEachSeries(a2, function(n2, callback) {
        console.log(n1 + " " + n2);
        callback();
    });
    callback();
});

I want to make the process of the above code in such a way that the print out becomes

1
1 10
1 11
1 12
1 13
1 14
2
2 10
2 11
2 12
2 13
2 14
3
3 10
3 11
3 12
3 13
3 14
.....

But instead I'm getting something like..

1
1 10
2
2 10
1 11
3
3 10
2 11
1 12
....

How do I fix this?

Quenchless answered 11/4, 2013 at 7:18 Comment(7)
If you need synchronous output, why do you perform it async?Batavia
hm. doesn't forEachSeries perform in a synchronous way?Quenchless
Both Node 0.10.3 and 0.8.16 produce the output you want on my Mac. Are you piping the output of the script to a file (or another program)? That changes the behaviour of process.stdout, and therefore console.log as well, so that might result in different output. And forEachSeries is synchronous in that the next iteration will only be called once the previous is done.Outfoot
Hm.. you're right. On my machine it does in fact produce the output you expected as well. But I would rather call it "in sequence" than "synchronous". I'm using node 0.10.3 btw.Batavia
@Batavia I guess it's a matter of semantics :) I'd call it synchronized since the operations are dependent on each other, (N+1) only gets called once (N) has completed.Outfoot
@Outfoot Yes, but between execution of (N+1) and (N), other stuff could happen, and it still could be "in sequence". But I agree, it's a matter of sematics :)Batavia
Strange, I wasn't piping the output to another program. The solution given by @spotirca worked well for me.Quenchless
L
17

The forEachMethod also accepts a callback when everything done. So your code should look like this:

var a1 = [1,2,3,4,5,6,7,8];
async.forEachSeries(a1, function(n1, callback_s1) {
    console.log(n1);
    var a2 = [10,11,12,13,14];
    async.forEachSeries(a2, function(n2, callback_s2) {
        console.log(n1 + " " + n2);
        callback_s2();
    }, function () {
        /* Finished the second series, now we mark the iteration of first series done */ 
        callback_s1();
    } );
});

The problem in your code is the fact that you assume async.forEachSeries to be synchronous, but it is not. It guarantees the fact the array will be handled synchronously, but the function itself is asynchronous.

Lush answered 11/4, 2013 at 9:32 Comment(2)
Could you please expand on "It guarantees the fact the array will be handled synchronously, but the function itself is asynchronous."? If each element of the array is handled synchronously, does that not imply the function applied TO each of the elements is also synchronous??Quenchless
Thanks! I had been breaking by head over this for two hours. Your answer cleared up the callback mechanism for nested async.*Smarten

© 2022 - 2024 — McMap. All rights reserved.