2013-12-17 54 views
2

所以我有一个嵌套的异步代码运行在一起很好的块,它似乎都没问题,除了当我到它的结尾。我在一系列块最后一个函数是一个foreach:那将会进入async.parallel正确使用async(with for each)

管理追查以下块不为了运行:

async.forEach(array, function(elem, callback) { 
     async.parallel([ 
      function(callback) { 
       database-call-A(elem, unction(err, data) { 
        if(err){ 
         console.log("error on first parallel"); 
         callback({err: false}); // will break out 
        } else { 
         elem.c = data; 
         callback(); 
        } 
       }); 
      }, 
      function(callback) { 
       database-call-B(elem, function(err, data) { 
        if(err){ 
         console.log("error on first parallel"); 
         callback({err: false}); // will break out 
        } else { 
         elem.c = data; 
         callback(); 
        } 
       }); 
      } 
     ]); // end async.parallel 

     // if forEach needs a callback after every iteration (which I think it does?) 
     console.log("PRINTS N TIMES - ONCE FOR EVERY ITERATION"); 
     callback(); // both parallel functions have run, call back forEach 

}); // end forEach 

console.log("Donions - prints when finished"); 

当我通过测试此代码我发现,“印刷N次...”跑了N次,然后我得到了“Donions ..”,然后我做了一些事情()。和其他东西();开始在我的async.parallel中调用。

为什么我的forEach迭代不等待async.parallel的回调?

回答

3

首先,没有async.forEach,但是有async.each函数。 async.parallel函数将同时执行所有任务,然后执行回调(如果已定义)。

在您的消息来源中,函数将在执行async.parallel后立即执行,而不是在所有函数都返回后执行。我建议你阅读documentation

如果要执行callback所有并行功能后回调已被调用,你应该通过forEach的回调到async.parallel功能作为第二个参数,功能的阵列之后。另外,您应该将回调传递给databaseCallAdatabaseCallB,这样当他们完成时就可以调用回调,这样他们就不会过早执行。

async.each(array, function(elem, callback) { 
    async.parallel([ 
     function(cb) { 
      databaseCallA(cb); 
      // if you have called the cb here, the `async.parallel` function would "think" that the databaseCallA has finished, even though it may not have started yet. 
     }, 
     function(cb) { 
      databaseCallB(cb): 
     } 
    ], callback); 
}); 

你应该修改数据库调用函数接受回调参数,使他们调用回调他们做他们的工作之后。

异步调用的目的是在等待工作完成时释放其他工作的资源 - 您的代码将继续执行,但您可以使用回调或某种基于事件的通知来通知其他人您的异步作业已完成。

编辑

为了毕竟并行调用已完成执行的东西:

async.each(array, function(elem, callback) { 
    async.parallel([ 
     function(cb) { 
      // I use the setTimeout function to intentionally 
      // delay the response 
      setTimeout(function() { 
       // the first cb parameter is error, the second is result 
       // in case there was no error 
       cb(undefined, 'a'); 
      }, 500); 
     }, 
     function(cb) { 
      setTimeout(function() { 
       cb(undefined, 'b'); 
      }, 300); 
     }, 
     function(cb) { 
      setTimeout(function() { 
       cb(undefined, 'c'); 
      }, 800); 
     } 
    ], function(err, results) { 
     // this will be executed only after all three cb's are executed. In 
     // this case, after about 800ms. The results variable will be an 
     // array containing the resuts passed to each cb. In this case it 
     // will be ['a', 'b', 'c']. 

     // you could call the main callback here 
     callback(); 
    }); 
}, function(err) { 
    // this callback will be executed either after everything was done, 
    // or if an error has occurred. 
    if (err) { 
     handleError(err); 
     return; 
    } 

    // this should be executed after all `each` and `parallel` calls 
    // have finished. In this case, it should also be after about 800ms 
    // from the start, since everything was executed in parallel 
    console.log('finished'); 

    // now you are sure everything was done, do something afterwards 
    after(); 
}); 

// this will be executed immediately so don't put anything here 
// that depends on the outcome of the async calls above 
console.log('test'); 
+0

你是对的!我在这里简化了一些,检查更新一点信息(我的数据库调用只回调一次,所以我们在这方面很好) - 我很确定forEach实际上是一个函数,考虑到它的运行在我的电脑,但我想知道为什么我永远无法在API上找到它 - 让我们看看它们是否都能做到。 – gadu

+0

那么你的问题究竟是什么? – jeremija

+0

正是我所描述的,我有我的并行之前并行运行后的代码 - 所以我的代码卡住,因为它不会退出forEach,因为这些回调已经发生。 – gadu

0

我不知道这个答案,但与异步文件根据,我认为你必须这样做:

async.forEach(array, function(elem, callback) { 
    async.parallel([ 
     function(callback) { 
      database-call-A(); 
      callback(); 
     }, 
     function(callback) { 
      database-call-B(): 
      callback(); // callback for second parallel function 
     } 
    ], function(err,result) { 
     // this code is executed when paralles functions ends 
     console.log("PRINTS N TIMES - ONCE FOR EVERY ITERATION"); 
     callback(); 
    }); // end async.parallel 

}); // end forEach 

关于。

+0

数据库调用是(应该)异步,在这种情况下,您的回调将在数据库调用实际完成一些工作之前执行。 – jeremija