asynchronousstream和全局variables
我开始学习一些node.js
和asynchronous事件玩杂耍,遇到了一个问题。
说我有n
不同的node.jsstream可读,我可以得到。 每个产生我想要存储的data
事件。 当所有的stream完成后,我想logging他们的所有结果在控制台。 我到目前为止:
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); } }); }
这个代码背后的想法是这样的:
对于从0
到n-1
每个i
,代码开始监听第i个可读stream,产生2n
监听stream的函数。 作为一个stream产生一个data
事件,我想存储到第i
个输出。 当所有的stream都完成后,我打印出他们的结果。
我提供的代码不起作用。 据我所知,问题是,当i
从1改变到2时,写在第1
stream上的函数现在要写到outputs[2]
而不是outputs[1]
,使得上帝糟糕透顶。
我的问题是这样的:
我知道我想做的事情最好是通过pipe
来实现。 但是,这是关于我学习asynchronous编程的原则,并希望通过这种方式推进。 我怎样才能避免像上面这样的情况全局variables( i
)搞乱我的callback函数? 有没有办法做我想做的确切的事情(当然,但实际上)?
谢谢。
您需要在自己的作用域中声明一个不会被for循环修改的新variables。 我build议closures。
观察这两个asynchronous代码块之间的差异,并尝试在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); })(); }
根据请求,不会在循环中创build多个函数的高效版本。 如果setTimeout在Node中传递第三个参数(传递给callback函数的参数),我们也可以在循环运行之前创buildsetATimeout
使用的匿名函数。
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); }
我有个主意。 Javascript的函数构造函数允许你定义一个函数体作为一个string:
ithReadable.on('data', new Function("chunk", "outputs[" + i + "] += chunk;");
文档: https : //developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function
尝试下面的代码。
在JavaScript中使用up-closure-scopevariables时应该小心。
Java需要闭包variables才是最终的价值。
与Java不同,Javascript允许修改闭包variables。
在这种情况下,您应该在某个对象内传递值而不是通过closuresvariables。
幸运的是,node.js在callback事件处理时传递“this”。
ithReadable.idx = i; ithReadable.on('data', function(chunk){ outputs[this.idx] += chunk; });
使用IIFE版本跟进@AlexMA
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 }