下划线:异步每个循环等待“内部”

时间:2013-10-11 10:27:20

标签: node.js underscore.js

我如何等待循环中的回调更改变量,仍然使用异步性?

第二个例子是使用异步,在这种情况下我不知道如何将第二个参数sum添加到wait,以避免全局var sum。称为wait(sum,value);,返回值为sum

wait是一个复杂函数的表示,我在我的实际问题中使用它,所以它不能被重写为“inline”-code并且必须保持“function”。

例1:

var _ = require('underscore');
var arr = [1,2,3,4,5,6,7];
var sum = 0;

function wait(item,callback) {
  setTimeout(function() {
    callback(item);
  }, Math.ceil(Math.random()*1000));
}

var done = _.after(arr.length,function(value) {
  console.log('sum ='+value);
})

_.each(arr,function(itm) {
  wait(itm,function(value) {
    console.log('waiting... '+value);
    sum = sum + value;
  })
 // Please wait for the callback
  console.log(itm);
  done(sum);
});

例2:

function asyncExample2() {
var async = require('async');
var arr = [1,2,3,4,5,6,7];

function otherWait(item, callback) {
    setTimeout(function() {
    callback(item); // call this when you're done with whatever you're doing
  }, Math.ceil(Math.random()*1000));
}

function wait(item, callback) {
  setTimeout(function() {
    otherWait(item,function() {
    console.log(item);
  });
  callback(item); 
  }, Math.ceil(Math.random()*1000));
}

function done() { console.log("sum = "+sum);};

var sum = 0;
async.forEach(arr, wait, done);
}

所需电话:

sum = wait(sum,item) 

4 个答案:

答案 0 :(得分:4)

最简单的方法是将done放入函数wait。只有在执行完done后才会调用callback

var arr = [1,2,3,4,5,6,7];
var sum = 0;

function wait(item,callback) {
  setTimeout(function() {
    callback(item);
    done(sum);
  }, Math.ceil(Math.random()*1000));
}

var done = _.after(arr.length,function(value) {
  console.log('sum ='+value);
})

_.each(arr,function(itm) {
  wait(itm,function(value) {
    console.log('waiting... '+value);
    sum = sum + value;
  })
  // Please wait for the callback
  console.log(itm);
  //done(sum);
});

输出:

enter image description here

答案 1 :(得分:2)

下划线完全同步,因此done(sum)将在wait执行完毕之前执行。 对于异步操作,请勿使用下划线。

像这样简单的事情应该做你想做的事情:

var sum = 0;
var waitNext = function(pos) {
    wait(arr[pos], function(value)) {
        if(pos < arr.length)
        {
            console.log('waiting... '+value);
            sum += value;
            waitNext(pos+1);
        }
        else
        {
            done(sum);
        }
    }
}
waitNext(0);

您当然可以避免使用waitNext而只是修改wait但如果wait不是您的代码,这将有效。 不确定您是否想要sum += value在if之前或之前,因为现在您可以通过调整if条件的顺序来删除不必要的waitNext电话。

答案 2 :(得分:2)

你可以真正做一个没有全局变量的递归版本。

  var arr = [1,2,3,4,5,6,7];

  function wait(arr, max, callback, sum, done) {
    var item = arr.shift();
      setTimeout(function(){
        if(item) {
          sum[0] = callback(item, sum[0]);
          sum[1]++;
        }
        else
          sum[1] === max ? done(sum[0]) : wait(arr,max, callback, sum, done);
      }, Math.random()*1000);
      item && wait(arr, max,callback, sum, done);
  }

  function cb(item, acc) {
    console.log('waiting....' + item);
    return item + acc;
  }

  function done(sum) {
     console.log(sum);
  }

  wait(arr, arr.length,cb, [0, 0], done);

输出 enter image description here

答案 3 :(得分:1)

我假设您正在使用setTimeout来实现 asynchronus 行为,而您可以使用像async这样的库,它可以更轻松地为您处理。

使用async's each

之前
var async = require('async');
var arr = [1,2,3,4,5,6,7];
var sum = 0;

async.forEach(arr, function(item, cb){
   sum = sum + item;
   cb();
}, function(err){
  console.log(sum);
});