【问题标题】:Node.js async.series() don't wait callback to completeNode.js async.series() 不要等待回调完成
【发布时间】:2014-11-26 09:17:05
【问题描述】:

mongoose.disconnect() 从未被调用并且节点程序有时间执行所有回调时,我的代码可以工作。当在程序结束时调用mongoose.disconnect() 并且连接丢失时,这些对 mongo 的插入自然不会发生。

此异步不等待这些插入完成。为什么,我该如何解决?

mObjectList = 准备插入的对象数组

insertMongoObj: function(mObjectList, callback) {
  var tasks = [];

  for (i in mObjectList) {
    tasks.push(mObjectList[i].save());
  }

  async.parallel(tasks, function(err) {
    if (err) {
      callback(err, 0);
    }
  });
  callback(null, tasks.length);
}

感谢您的快速回复!按照建议更改了功能,但同样的事情。当连接永远不会关闭并且程序永远不会退出时工作。 Mongoose.disconnect() 在这些插入之前仍在关闭连接。

insertMongoObj : function(mObjectList, callback){

    var tasks = [];

    for (i in mObjectList) {
      tasks.push(mObjectList[i].save.bind(mObjectList[i]));
    }

    async.parallel(tasks, function(err) {
        if(err) return callback(err);
        winston.info("  file processing ready");
    });

    return callback();
}

之前的函数调用在这里:

mongoose.connection.once('open', function () {
    talendToMongo.processTalendExport(objPaths, function(){
        mongoose.disconnect();
    });

});

processTalendExport : function(talendEntityLocationList, callback){
    var mongoObjectList = [];
    var self = this;
    for(obj in talendEntityLocationList){
        winston.info("**Start processing directory:" + talendEntityLocationList[obj]);
        var fileList = fs.readdirSync(talendEntityLocationList[obj]);
        this.processEntityDir(talendEntityLocationList[obj], fileList, function(mongoObjectList){
            self.insertMongoObj(mongoObjectList, function(err){
                if(err) {
                    winston.error("  Error processing file:" + talendEntityLocationList[obj]);
                        process.exit(0);
                    } else {
                        winston.info(" Mongo Objects inserted");
                    }
                });
            });
        }
        callback();
    }

insertMongoObj : function(mObjectList, callback){
    var tasks = [];

    for (i in mObjectList) {
        tasks.push(mObjectList[i].save.bind(mObjectList[i]));
    }

    async.parallel(tasks, function(err) {
        if(err) return callback(err);
          winston.info("  file processing ready");
        });

        return callback();
    }

【问题讨论】:

  • 因此异步...您不是在等待任务完成,您有 2 个选择,显而易见的一个是 Dan 提供的,第二个是使用某种计数器来跟踪竞争任务......你可能不想那样做。
  • 只是一个小建议;当执行任务出错时,不要将零传递给回调。只传递错误对象。

标签: javascript node.js mongodb async.js


【解决方案1】:

您需要将最后一次回调调用移动到 async.parallel 的回调中:

for (i in mObjectList) {
  tasks.push(mObjectList[i].save.bind(mObjectList[i]));
}

async.parallel(tasks, function(err) {
     if (err) {
         return callback(err, 0);
     }
     return callback(null, tasks.length);
 });

【讨论】:

  • 在错误情况下仍然调用回调两次。此外,mObjectList[i].save() 在添加到任务列表之前正在执行。应该是tasks.push(mObjectList[i].save)
  • @BenTaber:他使用return 来避免两次调用回调。如果您不喜欢这种风格,请使用更明显的else
【解决方案2】:

这是一个很好的例子,async.each 是理想的。

insertMongoObj: function(mObjectList, callback) {
    async.each(mObjectList, function(obj, done){
        obj.save(done);
    }, callback);
}

更新

processTalendExport 中,callback()for(obj in talendEntityLocationList){ 循环之后而不是在插入完成之后,因此它会在插入完成之前调用.disconnect。取决于客户端和网络,这可能总是会导致失败,或者只是有时会失败。您也应该使用async.each(talendEntityLocationList, ... 来查看该列表。

【讨论】:

  • 谢谢!也测试了这个,但同样的事情。调用 disconnect() 时,不会在 Mongo 中插入任何内容。在不关闭连接的情况下插入所有文档.....
  • 您在callback 内打电话给disconnect 吗?我需要查看调用insertMongoObj 的代码才能说更多。
  • 添加了您请求的呼叫。感谢您的帮助。这对我来说不是展示停止器,而是当事情没有按计划进行时很烦人......
【解决方案3】:

终于让这个工作更正了以前的函数回调并修复了 async.eachSeries 回调:

    insertMongoObjects : function(mongoObjList, callback){
        var insertCnt = 0;
        winston.info("    Start mongo object insert");
        async.eachSeries(mongoObjList,
            function(mongoObj, done){
                    mongoObj.save(function(save_result){
                        if(!save_result){ 
                            insertCnt++
                            done(null);
                        } else { done(save_result); }
                    });
            },
            function(err){
                if(err) {
                    winston.error("    Error inserting mongo object:");
                    winston.error(err);
                    callback(err);
                } else {
                    winston.info("    Mongo object insert successful for:" + insertCnt);
                    callback();
                }
            }
        );
    }

【讨论】:

    猜你喜欢
    • 2016-02-17
    • 1970-01-01
    • 1970-01-01
    • 2016-03-09
    • 2020-07-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-19
    相关资源
    最近更新 更多