异步流和全局变量

时间:2014-03-21 15:01:16

标签: javascript node.js

我开始学习一些node.js和asynchronus事件杂耍并遇到问题。

说我有n个不同的node.js流可读,我可以得到。每个都会生成我要存储的data个事件。当所有流完成后,我想在控制台中记录所有结果。到目前为止我所拥有的:

outputs = [];
//Construct an array in which the outputs will wait for the streams to finish:
for(var i = 0; i < n; i++){
     outputs.push('');
}
ended = 0;
for(var i = 0; i < n; i++){
    var ithReadable = getReadableStreamSomehow(i); // produces the i-th readable stream.
    ithReadable.on('data', function(chunk){
        outputs[i] += chunk;
    });
    ithReadable.on('end', function(chunk){
        ended++;
        if (ended == n){
            console.log(outputs);
        }
    });
}

此代码背后的理念是:

对于从i0的每个n-1,代码开始侦听第i个可读流,生成监听流的2n函数。当流生成data事件时,我想将其存储到i - 输出中。当所有流完成后,我打印出他们的结果。

我提供的代码不起作用。据我了解,问题是当i从1更改为2时,编写为侦听1流的函数现在要写入outputs[2]而不是{ {1}},让上帝变得糟透了。

我的问题是:

我知道我想做的事情最好通过outputs[1]来实现。然而,这是关于我学习异步编程的原理并希望以这种方式推进。我怎样才能避免像全局变量(pipe)弄乱我的回调函数的情况?有没有办法做我想做的事情(但实际上是在工作)?

谢谢。

4 个答案:

答案 0 :(得分:2)

您需要在自己的作用域中声明一个不会被for循环修改的新变量。我建议关闭。

观察这两个异步代码块之间的区别,并尝试在Chrome控制台中运行它们:

for(var i = 0; i < 10; i++){
  setTimeout(function(){ //This function is asynchronous.
     console.log(i);
  }, 1000);
}

第2版:

for(var i = 0; i < 10; i++){
  // This anonymous function executes immediately, once per loop, and is not asynchronous
  (function(){         
     var k = i;  // once k is instantiated it will not be modified again.
     setTimeout(function(){
        console.log(k);
     }, 1000);
  })();  
}

每个请求,这个高效版本不会在循环中创建任意数量的函数。如果setTimeout在Node中接受了第三个参数(传递给回调的参数),我们还可以在循环运行之前创建setATimeout中使用的匿名函数。

function setATimeout(i){
   // i was passed by value since it is a primitive, so no scope problems.
      setTimeout(function(){
        console.log(i); 
     }, 1000);
}

for(var i = 0; i < 10; i++){
  setATimeout(i);
}

答案 1 :(得分:0)

我有个主意。 Javascript的函数构造函数允许您将函数体定义为字符串:

ithReadable.on('data', new Function("chunk", "outputs[" + i + "] += chunk;");

文档:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function

答案 2 :(得分:0)

请尝试以下代码。

在javascript中使用up-closure-scope变量时应该小心。

Java要求闭包变量为最终值。

与Java不同,Javascript允许修改闭包变量。

在这种情况下,您应该在某个对象中传递值而不是闭包变量。

幸运的是,node.js在回调事件处理时传递“this”。

ithReadable.idx = i;
ithReadable.on('data', function(chunk){
    outputs[this.idx] += chunk;
});

答案 3 :(得分:0)

跟进@AlexMA和IIFE版本

for(var i = 0; i < 10; i++){
  // This anonymous function executes immediately, once per loop, and is not asynchronous
  (function(k){
     //k is local it will not be modified.
     setTimeout(function(){
        console.log(k);
     }, 1000);
  })(i);  // pass i to anonymous function
}