【问题标题】:How to wait for all async calls to finish如何等待所有异步调用完成
【发布时间】:2011-10-04 03:52:45
【问题描述】:

我将 Mongoose 与 Node.js 一起使用,并且有以下代码将在所有 save() 调用完成后调用回调。但是,我觉得这是一种非常肮脏的做法,并希望看到完成此操作的正确方法。

function setup(callback) {

  // Clear the DB and load fixtures
  Account.remove({}, addFixtureData);

  function addFixtureData() {
    // Load the fixtures
    fs.readFile('./fixtures/account.json', 'utf8', function(err, data) {
      if (err) { throw err; }
      var jsonData = JSON.parse(data);
        var count = 0;
        jsonData.forEach(function(json) {
          count++;
          var account = new Account(json);
          account.save(function(err) {
            if (err) { throw err; }
            if (--count == 0 && callback) callback();
          });
        });
    });
  }
}

【问题讨论】:

标签: node.js mongoose


【解决方案1】:

您可以使用 asyncStep 之类的库稍微清理一下代码。

另外,我编写了一个小模块来为您处理加载装置,所以您只需这样做:

var fixtures = require('./mongoose-fixtures');

fixtures.load('./fixtures/account.json', function(err) {
  //Fixtures loaded, you're ready to go
};

Github: https://github.com/powmedia/mongoose-fixtures

它还会加载一个夹具文件或对象的目录。

【讨论】:

  • 如果使用夹具库,我建议使用以下更新的项目,它更快且维护更积极:github.com/powmedia/pow-mongodb-fixtures
  • 是的 .. pow-mongodb-fixtures 更快,但 mongoose-fixtures 会验证您的灯具是否符合 mongoose 模型(例如字段匹配等)。它还可以使用对夹具数据非常方便的虚拟属性。
【解决方案2】:

我讨论了常见的异步模式(串行和并行)以及解决它们的方法:

https://github.com/masylum/i-love-async

我希望它有用。

【讨论】:

    【解决方案3】:

    我最近创建了名为 wait.for 的更简单的抽象来在同步模式下调用异步函数(基于 Fibers)。它处于早期阶段,但有效。它位于:

    https://github.com/luciotato/waitfor

    使用 wait.for,您可以调用任何标准的 nodejs 异步函数,就像它是一个同步函数一样,而不会阻塞节点的事件循环。您可以在需要时按顺序编码。

    使用 wait.for 您的代码将是:

    //in a fiber
    function setup(callback) {
    
      // Clear the DB and load fixtures
      wait.for(Account.remove,{});
    
      // Load the fixtures
      var data = wait.for(fs.readFile,'./fixtures/account.json', 'utf8');
    
      var jsonData = JSON.parse(data);
      jsonData.forEach(function(json) {
        var account = new Account(json);
        wait.forMethod(account,'save');
      }
      callback();
    }
    

    【讨论】:

      【解决方案4】:

      这实际上是正确的做法,或多或少。你在那里做的是一个并行循环。如果需要(很多人都这样做),您可以将其抽象为它自己的“异步并行 foreach”函数,但这确实是进行并行循环的唯一方法。

      根据您的意图,可以以不同方式完成的一件事是错误处理。因为你在抛出,如果有一个错误,回调将永远被执行(count 不会被递减)。所以这样做可能会更好:

      account.save(function(err) {
        if (err) return callback(err);
        if (!--count) callback();
      });
      

      并在回调中处理错误。它在节点约定方面更好。

      我还会更改另一件事,以免您在每次迭代时增加 count 的麻烦:

      var jsonData = JSON.parse(data)
        , count = jsonData.length;
      
      jsonData.forEach(function(json) {
        var account = new Account(json);
        account.save(function(err) {
          if (err) return callback(err);
          if (!--count) callback();
        });
      });
      

      【讨论】:

        【解决方案5】:

        如果您已经在项目中的任何位置使用underscore.js,则可以利用after 方法。您需要提前知道会有多少异步调用,但除此之外,这是一个非常优雅的解决方案。

        【讨论】:

          猜你喜欢
          • 2016-03-16
          • 2020-02-22
          • 1970-01-01
          • 2015-06-09
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多