如何累积异步数据?

时间:2013-12-11 16:45:46

标签: algorithm node.js design-patterns asynchronous

我想总结一下异步生成的数据(在node.js中)。 你会如何以线程安全的方式做到这一点?

例如,

function test(){
  var accumulator = 0;
  for(int i= 0; i<100; i++){
    // non blocking function producing value
    getasyncdata(i, function(value){
      // this is spread over 3 lines to simulate non atomic operation.
      tmp = accumulator;
      tmp = tmp + value;
      accumulator = tmp;
    });
  }
  console.log(accumulator);
}

我看到getdata回调的方式将在并行中被调用100次...并且由于回调不是原子的(或者是?),因此累积器不会是100个值的总和。 / p>

您怎么看?

2 个答案:

答案 0 :(得分:2)

您可以使用检查任何作业是否正在运行的函数,然后在完成后打印。例如:

function test(){
  var accumulator = 0, pendingOps = 0;

  for(int i= 0; i<100; i++){
    // non blocking function producing value
    pendingOps++;
    getasyncdata(i, function(value){
      // this is spread over 3 lines to simulate non atomic operation.
      tmp = accumulator;
      tmp = tmp + value;
      accumulator = tmp;
      printIfFinished();
    });

    function printIfFinished() {
      pendingOps--;
      if(pendingOps) == 0 {
        console.log(accumulator);
      }
    }
  }
}

有很多控制流程库可以帮助你做到这一点,其中两个比较流行的是:

答案 1 :(得分:-1)

虽然实际的异步操作可能同时发生(在单独的线程中),但由于Nodes事件循环是单线程的,因此在给定时间只会触发一个回调。因此,保证accumulator确实是所有值的总和。

至于您的示例代码,console.log(accumulator)将为零,因为getasyncdata是非阻塞的,因此console.log将在异步调用完成之前执行。如果您希望记录最终累积的数据,您可以这样实现:

function test() {
    var accumulator = 0;
    var counter = 0;
    for (int i = 0; i < 100; i++) {
        // non blocking function producing value
        getasyncdata(i, function (value) {
            // this is spread over 3 lines to simulate non atomic operation.
            tmp = accumulator;
            tmp = tmp + value;
            accumulator = tmp;
            counter++;
            if (counter == 100) {
                console.log(accumulator);
            }
        });
    }
}