嵌套异步循环向异步队列推送时未调用主回调函数

5

我有一个异步队列,我正在向其中推送一些东西。我生成需要推入队列的项目的方式是通过遍历数据对象中的几个嵌套列表。队列最终会处理所有内容,但由于某种原因,我无法通过 console.log('All done.') 访问我的主回调函数。我已经删除了大部分不必要的内容,只留下了异步内容。我做错了什么?我漏掉了什么吗?

var q = async.queue(function(task, callback) {
  console.log('hello ' + task);
  callback();
}, 2);

function A(data) {
  B(data, function() {
    // THIS ISN'T getting called. 
    console.log('All done.');
  })
}

function B(data, callback1) {
  var list = [[1,2], [3,4], [5,6]];
  async.each(list, function(item, callback1) {
    async.each(item, function(i, callback2) {
      doWork(i, function() {
        console.log('Work done');
      })
      callback2();
    }, 
    // THIS should be called when everything in this each is done. 
    callback1)
  })
}

function doWork(i, callback3) {
  q.push(i, callback3);
} 

为了帮助澄清问题:您得到了什么输出?您期望得到什么?调用A和B的代码在哪里? - hugomg
所有的“hello” + 任务和“Work done”都被打印出来了。但是只有主要的“全部完成”没有被打印出来。 - owenlero
请修复您的代码片段,使其至少在语法上正确,否则很难弄清楚。 - soulcheck
1个回答

1

这是一些带有注释的代码,因为谈论回调函数嵌套会比较复杂:

function B(data, callback1 //this is what you want to be called) {
  var list = [[1,2], [3,4], [5,6]];

  //async1
  async.each(list, function(item, callback1 //now callback1 is a function passed to your code by `async.each` not the original callback1) {
      //async2 
      async.each(item, function(i, callback2) {
      doWork(i, function() {
        console.log('Work done');
      })
      callback2();
    }, 
    // THIS is actually called, it's just a different function than you think it is 
    callback1)
  })
}

问题在于您在B的参数和async1回调函数的回调参数中使用了相同的名称。
因此,在async1回调中的callback1隐藏了外部的callback1,实际上是内部的async1回调,它用于将控制权传递回async.each
解决方案很简单:重命名async1回调参数,例如:
function B(data, callback1) {
  var list = [[1,2], [3,4], [5,6]];
  async.each(list, function(item, async1_callback) { //here lies the rename
    async.each(item, function(i, callback2) {
      doWork(i, function() {
        console.log('Work done');
      })
      callback2();
    }, 
    // this is now called as expected 
    callback1
    ); 
    // BUT we forgot to call the async1_callback, so let's do it:
    async1_callback();

};

按预期工作。

谢谢,真不敢相信我错过了那个...但另一个问题是它首先输出“全部完成” - 当循环正确完成时,它应该最后输出,对吗?我还错过了什么吗? - owenlero
仍然缺少对async1_callback()的调用 - 请检查更新。至于先打印“全部完成” - 这可能是因为async.each和队列操作都没有在任何地方调用process.nextTick,而且您的代码没有让事件循环暂停。至于只打印一次 - 只需将其作为最终回调添加到async1中,而不是async2。 - soulcheck

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接