为什么Async.parallel回调会返回意外结果?

时间:2014-11-13 18:06:16

标签: javascript node.js asynchronous

以下函数是我工作的一点点复杂函数的抽象版本。有人能告诉我为什么async.parallel的回调会返回一个不同于allitems数组的值,而不是要返回我期望的数组的waterfallfunction2吗?

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!");

});

2 个答案:

答案 0 :(得分:1)

难以阅读你的回调地狱...... 我试着写同样的东西而且都有效:)

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);
});

我发现了一个错误!你是呼叫回叫,而不是通过并行呼叫传递它! =)
只需将callback(null)更改为要传递回调的callback

答案 1 :(得分:0)

你不应该直接调用callback(null)作为async.each()中的第三个参数。实际上,您通过直接执行回调(null)来调用回调2级。相反,你应该将该调用包装在一个函数中,以便它按你的想法工作。

这很好用:

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!");

});