如果我遗失了什么,我很抱歉 - 我还在学习Node的逻辑(特别是异步工作)。
我想下载一个zip文件,然后将其保存并解压缩。它看起来像这样:
request(URL)
.pipe(fs.createWriteStream(/path/to/filename))
.on('close', function () {
// I want to unzip and I need access to filename
});
现在的问题是,如果我事先设置了filename
变量,因为它处于循环中,到文件下载时,filename
将具有最后一次循环迭代的值。 / p>
当然,我发现我们可以通过定义一个可以完成所有这些工作的函数来完成它,比如fecthAndUnzip(URL,path)
。但我的问题是与设计相关:它是我们在Node中做到这一点的唯一方法,还是有更好的方法?例如,我可以在on('close')
事件中访问文件名,如果是,我应该吗?谢谢!
答案 0 :(得分:1)
Don't know if it's helping you but the problem you describe in for loop has multiple solutions :
first one, use let instead of var to bind the variable to it's current scope :
for (let i = 0; i < 4; i++) {
setTimeout(function() {
console.log('test 2', i);
}, 2000);
}
this will print 0, 1, 2, 3 even if loop will end before the first timeout callback is called.
You can use forEach instead of for loop if it's an array
[0, 1, 2, 3].forEach(function(i) {
setTimeout(function() {
console.log('test 3', i);
}, 3000);
})
you can use an external function :
for (var i = 0; i < 4; i++) {
setTimeout(function() {
logI(i);
}, 100);
}
function logI(i) {
console.log(i);
}
the only thing that matter is that your variable needs to be bound to an internal scope to keep it's value even if the loop ends before your asynchonous function is called.
答案 1 :(得分:1)
定义一个单独的函数绝对不是唯一的方法,并且有一个更好的方法。
您没有显示完整代码,但我认为由于您使用var
来定义变量的行为。与var filename = 'something'
中一样。执行此操作时,您将在global [function]范围中定义filename变量。这意味着无论函数在何处定义,它都可用于函数的每个部分。在你的情况下,即使你在循环中定义变量,它也是整个函数的范围,所以你实际上每次迭代都会覆盖那个变量。
如果您想了解更多内容或者我没有充分解释这个范围,那么有关于范围的一个很好的stackoverflow答案:https://stackoverflow.com/a/11444416/6359249
解决方案是在当前块范围内定义变量。如果您使用的是实现ES6的较新版本的node.js,则可以使用let
(或const
作为常量变量)。与var
不同,这将在当前块中定义一个函数。如果在循环中定义它,则只能访问该块,并且不会更改。例如:
for (let i = 0; i < files.length; i++) {
let filename = files[i];
// Do stuff
}
注意let i = 0
。相同的范围概念适用于循环变量。这是人们使用var i = 0
时常见的问题,并且在使用异步函数时会感到困惑,并且发现i
是i
的最后一个值。
如果您不使用ES6,您可以在每个循环中定义一个匿名函数:
for (var i = 0; i < files.length; i++) {
var filename = files[i];
(function (file) {
// Do stuff
})(filename);
}
除了您即时创建和执行该功能外,其与您描述的解决方案相同。如果您由于某种原因没有使用ES6,那么创建单独功能的原始答案可能是最佳解决方案。