node.js async.eachSeries 过早调用最终回调

Posted

技术标签:

【中文标题】node.js async.eachSeries 过早调用最终回调【英文标题】:node.js async.eachSeries calling final callback too early 【发布时间】:2014-03-10 19:58:17 【问题描述】:

这就是我想要的:我有一个名为 results 的大数组。我想将该数组中的每个项目放入我的迭代函数中并将其保存到我的 mongoDB 中(我在这里也省略了一些不重要的步骤)。在将这些项目中的每一项都保存到数据库(或拒绝)之后,我希望 console.log 显示“全部完成”。不幸的是,在调用系列后几乎立即显示所有完成,而其他一切仍在处理中。我该怎么做?

我将猫鼬与一个名为“light”的模型一起使用,为了便于阅读,我省略了代码中的所有错误消息。我对 eachSeries 部分使用节点异步

var async = require('async');    
var results = [very big array]
var iteration = function(row,callbackDone) 
  light.find(data: row.data, function (err,entry) 
    if(entry.length) 
      callbackDone();
      return console.log(entry + ' already exists');
    
    var newEntry = new light(row);
    newEntry.save(function (err,doc) 
      console.log(entry + ' saved');
      callbackDone();
    );
  );
;

async.eachSeries(results,iteration, function (err) 
  console.log('All done');
);

【问题讨论】:

尝试添加一些错误记录器 (if (err) console.log(err);)。 为了便于阅读,我删除了错误记录器。对不起,如果我不清楚。该数组很容易有 100 多个条目,猫鼬操作完美无缺,但所有保存都发生在 console.log('all done') 显示之后。我需要的是一种在我的数组中的所有项目都已处理完之后显示“全部完成”的方法 【参考方案1】:

(答案,不是评论,因为文字太长了……)

我也在使用异步,你的问题让我很困惑。我尝试了下面的代码,结果更进一步。它对我来说很好。 (异步 0.2.9)。甚至将我的超时延迟更改为 0。

唯一看起来奇怪的是回调后的if(entry.length) 块打印控制台信息。如果您收到很多“已经存在”的消息,我可能会看到它们稍后会出现 - 但这听起来不像您所描述的那样。

var async = require('async');  
var console = require('console');
var results = [ ];
results.push( id:1,data:'a' );
results.push( id:2,data:'b' );
results.push( id:3,data:'c' );
results.push( id:4,data:'d' );

function doFind( obj, callback ) 
  setTimeout( function() 
    console.log( "finding id=" + obj.data.id );
    obj.data.length = obj.data.id % 2;
    callback( null, obj.data );
  , 500 );


function light( obj ) 
  this.id = obj.id;
  this.data = obj.data;
  this.save = function( callback ) 
    setTimeout( function() 
      console.log( "saving id=" + obj.id );
      callback( null, this );
    , 500 );
  ;


var iteration = function(row,callbackDone) 
  doFind(data: row, function (err,entry) 
    if(entry.length) 
      callbackDone(); 
      return console.log( 'id=' + entry.id + ' already exists');
    
    var newEntry = new light(row);
    newEntry.save(function (err,doc) 
      console.log( 'id=' + entry.id + ' saved');
      callbackDone();
    );
  );
;

async.eachSeries(results, iteration, function (err) 
  console.log('All done');
);

结果

finding id=1
id=1 already exists
finding id=2
saving id=2
id=2 saved
finding id=3
id=3 already exists
finding id=4
saving id=4
id=4 saved
All done

【讨论】:

您的示例也非常适合我,但由于某种原因我无法解决自己的问题。我切换到 var stream = light.find().stream();解决方案并停止流,直到异步响应到来。可能有点难看,但它对我有用。非常感谢您的意见!

以上是关于node.js async.eachSeries 过早调用最终回调的主要内容,如果未能解决你的问题,请参考以下文章

node.js async.eachSeries 过早调用最终回调

嵌套节点 async.eachSeries

嵌套节点 async.eachSeries

使用Node.js管理多个文件流

嵌套在 async.eachSeries 循环中的 async.series 终止提前发送 POST 响应

如何在caolan async中使用await?