运行异步函数N次,其中N取决于调用返回的内容

时间:2014-03-15 00:59:37

标签: javascript node.js asynchronous

我正在处理mongoDb(https://jira.mongodb.org/browse/SERVER-1243)的限制,这迫使我运行update()次N次,直到我最终得到“0”作为总更新记录(太棒了呃? )。

所以,我必须转过身来:

_mongoUglyUpdateWrapper: function( querySelector, updateObject, options, cb ){

  var self = this;
  var total = 0;

  self.collection.update( querySelector, updateObject, options, function( err, partialTotal ){
    if( err ) return cb( err );
    cb( null, partialTotal );
  });
},

重复调用self.collection.update直到partialTotal最终为0的东西 - 此时它最终可以调用回调。我通常使用异步,但这里非常不同。

它需要递归,但我不确定解决此问题的最佳最简单方法是什么。帮助

(偏离主题:是的,就性能而言,这可能是一场灾难,但这就是当你信任年轻技术时所得到的;我写的下一层是MySql)。

3 个答案:

答案 0 :(得分:1)

我能想到的最好的方法是命名函数并检查函数内部:

_mongoUglyUpdateWrapper: function( querySelector, updateObject, options, cb ){

  var self = this;
  var total = 0;

  function checkIfZero( err, partialTotal ) {
    if( err ) return cb( err );
    if( partialTotal !== 0 ) return self.collection.update( querySelector, updateObject, options, checkIfZero );
    cb( null, partialTotal );
  }

  self.collection.update( querySelector, updateObject, options, checkIfZero );
},

答案 1 :(得分:1)

您可以使用async.doWhilst(或类似的async.doUntil,我觉得这更自然)。将更新记录的数量存储在函数外部的变量中,以便真值测试可以访问它。使用doWhilst代替whilst,以确保该功能运行一次。如果计数在运行后仍然为零,则表示您已完成(async负责处理)。

答案 2 :(得分:0)

答案版本#1,感谢Qantas 94 Heavy,使用checkIfZero

_mongoUglyUpdateWrapper: function( querySelector, updateObject, options, cb ){

  var self = this;
  var total = 0;

  var rnd = Math.floor(Math.random()*100 );

  function checkIfZero( err, partialTotal ) {
    if( err ) return cb( err );

    total += partialTotal;

    if( partialTotal !== 0 ){
      return self.collection.update( querySelector, updateObject, options, checkIfZero );
    }

    cb( null, total );
  }

  self.collection.update( querySelector, updateObject, options, checkIfZero );
},

版本#2,使用async.shilst可能在堆栈上更加温和。(感谢Henry Merriam)

_mongoUglyUpdateWrapper: function( querySelector, updateObject, options, cb ){

  var self = this;
  var total = 0;
  var partialTotal;

  async.whilst(
    function() { return partialTotal != 0 },

    function( callback ){

      self.collection.update( querySelector, updateObject, options, function( err, t ){
        if( err ) return callback( err );          

        total += t;

        partialTotal = t;
        callback( null );
      });
    },
    function (err) {
      if( err ) return cb( err );
      cb( null, total );
    }
  );
},