2

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

第二个例子是使用异步,在这种情况下,我不知道如何添加第二个参数sumwait以避免全局变量sumwait(sum,value);像返回值一样调用sum

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

示例 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

4 回答 4

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);
});

输出:

在此处输入图像描述

于 2013-10-12T05:04:40.930 回答
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);

输出 在此处输入图像描述

于 2013-10-12T06:31:33.930 回答
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 内部或之前,因为现在有一个不必要的waitNext调用,您可以通过调整 if 条件的顺序来删除。

于 2013-10-11T10:39:52.373 回答
1

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

例如使用异步的每个

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);
});
于 2013-10-11T10:44:01.140 回答