简体   繁体   中英

Why does Async.parallel callback return unexpected result?

the following function is an abstracted version of a little bit more complex function im working on. Can someone tell me why the callback of async.parallel returns a different value for the allitems array than waterfallfunction2 which return the array i expected?

var async = require('async');

async.waterfall([


    //Waterfallfunction 1
    function(callback) {
        var allitems = [];
        async.parallel([
                //Parallel 1
                function(callback) {
                    console.log("Waterfall 1 -> parallel 1");
                    async.each([1, 2, 3, 4, 5, 6], function(item, callback) {
                        allitems.push(item * 3);
                        callback(null);
                    }, callback(null));
                },
                //Parallel 2
                function(callback) {
                    console.log("Waterfall 1 -> parallel 2");
                    async.each([1, 2, 3], function(item, callback) {
                        allitems.push(item * 3 * 9);
                        callback(null);
                    }, callback(null));
                },
                //Parallel 3
                function(callback) {
                    console.log("Waterfall 1 -> parallel 3");
                    async.each([1, 2, 3, 4, 5, 6, 7, 8, 9], function(item, callback) {
                        allitems.push(item * 2);
                        callback(null);
                    }, callback(null));
                }

            ],
            //Callback parallel completed
            function(err, results) {
                if (err) {
                    callback(err);
                }

                console.log("Waterfall 1 parallel completed");
                //I expect all item to be
                //[ 3, 6, 9, 12, 15, 18, 27, 54, 81, 2, 4, 6, 8, 10, 12, 14, 16, 18 ]
                console.log(allitems);
                // but it logs
                // [ 3, 6, 9, 12, 15, 18, 27, 54, 81 ]


                //pass allitems to the next function in waterfall
                callback(null, allitems);
            });
    },
    // Waterfallfunction2
    //calculate items length
    function(allitems, callback) {


        var itemlength = allitems.length;

        //pass itemlength to next function
        callback(null, itemlength);
    },

    //Waterfallfunction3
    //Log Message
    function(itemlength, callback) {

        console.log("The array is " + itemlength + " long");
        callback(null);
    }
],
//Callbackfunction on Waterfall completed
function(err, result) {
    if (err) {
        console.log(err);
    }
    console.log("operations completed!");

});

It is too hard to read your callback hell...
I try to write same thing and all works :)

var async = require('async');

var cascade1 = function(next) {
    var all = [];
    async.parallel([
        function task1(next) {async.each([1, 2, 3], function(i, next){all.push(i);next();}, next) },
        function task2(next) {async.each([1, 2, 3], function(i, next){all.push(2*i);next();}, next) },
        function task3(next) {async.each([1, 2, 3], function(i, next){all.push(3*i);next();}, next) },
    ], function(){
        next(null, all);
    });
};

var cascade2 = function (items, next) {
    console.log(items);
    next(null, items.length);
}

async.waterfall([cascade1, cascade2], function(err, len){
    console.log(err, len);
});

I found a bug! You are call callback instead of passing it in parallels calls! =)
Just change callback(null) to callback where you want to pass callback.

You shouldn't call callback(null) directly as the third param in async.each(). You are in fact calling a callback 2 levels up by doing callback(null) directly. Instead you should wrap that call inside a function so it works as you think.

This works fine:

var async = require('async');

async.waterfall([


    //Waterfallfunction 1
    function(callback) {
        var allitems = [];
        async.parallel([
                //Parallel 1
                function(callback) {
                    console.log("Waterfall 1 -> parallel 1");
                    async.each([1, 2, 3, 4, 5, 6], function(item, callback) {
                        allitems.push(item * 3);
                        callback(null);
                    }, function() {callback(null)});
                },
                //Parallel 2
                function(callback) {
                    console.log("Waterfall 1 -> parallel 2");
                    async.each([1, 2, 3], function(item, callback) {
                        allitems.push(item * 3 * 9);
                        callback(null);
                    }, function() {callback(null)});
                },
                //Parallel 3
                function(callback) {
                    console.log("Waterfall 1 -> parallel 3");
                    async.each([1, 2, 3, 4, 5, 6, 7, 8, 9], function(item, callback) {
                        allitems.push(item * 2);
                        callback(null);
                    }, function() {callback(null)});
                }

            ],
            //Callback parallel completed
            function(err, results) {
                if (err) {
                    callback(err);
                }

                console.log("Waterfall 1 parallel completed");
                //I expect all item to be
                //[ 3, 6, 9, 12, 15, 18, 27, 54, 81, 2, 4, 6, 8, 10, 12, 14, 16, 18 ]
                console.log(allitems);
                // but it logs
                // [ 3, 6, 9, 12, 15, 18, 27, 54, 81 ]


                //pass allitems to the next function in waterfall
                callback(null, allitems);
            });
    },
    // Waterfallfunction2
    //calculate items length
    function(allitems, callback) {


        var itemlength = allitems.length;

        //pass itemlength to next function
        callback(null, itemlength);
    },

    //Waterfallfunction3
    //Log Message
    function(itemlength, callback) {

        console.log("The array is " + itemlength + " long");
        callback(null);
    }
],
//Callbackfunction on Waterfall completed
function(err, result) {
    if (err) {
        console.log(err);
    }
    console.log("operations completed!");

});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM