async.eachSeriescallback调用多次

在这个function中:

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

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

我认为你的问题在这里:

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

您多次调用cb1 ,这会导致最外层的async.eachSeries继续多次,因此多次调用最终的callback

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

 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调用,因此我必须假设这是一个事务性函数,所以您应该使用callback将其更改为fs.readFile

第二个好处:当然,太过分了,这种嵌套变成一团糟。 有办法用function性编程技术来解决这个问题。