async.eachSeries多次调用回调

时间:2014-02-28 14:45:23

标签: javascript node.js node-async

在此功能中:

function method2(friends, callback) {
    //friends is an array of objects
    var ids = _.pluck(friends, 'id'),
        arrays = cut(ids, 24),
        //cut() splits array into smaller arrays of given length 
        code = require('fs').readFileSync('...').toString();
    var imp,j;
    async.eachSeries(arrays, function(i, cb1) {
        ...
        vk.request('execute', {code:code}, function(err, resp, body) {
            //vk.request passes its callback to node-request module
            //at this point, err is null, and body.error is undefined
            if(err || body.error) return cb1(err || body.error);
            var arr = body.response;
            for(var e in arr) {
                if(!arr[e]) return cb1();
                async.eachSeries(arr[e], function(i, cb) {
                    ...
                    cb();
                }, cb1);
            }
        })
    }, callback);
}

函数只被调用一次,但异步调用多次回调而不提供任何参数。我看不出任何原因。那么这段代码有什么问题呢?

1 个答案:

答案 0 :(得分:3)

我认为你的问题在这里:

for(var e in arr) {
    // ...
    async.eachSeries(/* ... */, cb1);

您多次致电cb1,这会导致最外面的async.eachSeries多次继续,因此最后callback会被多次调用。

解决方案:使用async.each而不是简单的for循环来生成多个并发内部async.eachSeries循环(如果这真的是你想要的)。这是嵌套异步循环的方法:

async.eachSeries(/* ... */, function(/* ... */, cb1) {
  // this body runs once at a time
  async.each(/* ... */, function(/* ... */, cb2) {
    // this body runs multiple times 'concurrently'
    async.eachSeries(/* ... */, function(/* ... */, cb3) {
       // this body runs sequentially,
       // but multiple sequential runs can happen at once
       cb3(/* ... */);
    }, cb2);
  }, cb1);
}, callback);

一个非主题奖励:除了在应用程序启动时使用readFileSync是不可取的(当且仅当使用require时是安全的,使用readFileSync也是安全的)。由于您正在使用async调用,因此我必须假设这是一个事务函数,因此您应该使用回调将其更改为fs.readFile

第二个奖励:当然,走得太远,这种嵌套变成了一大堆。 There are ways to combat this using functional programming techniques.