请求和写入流文件名
Request and writeStream filename
如果我遗漏了什么,我很抱歉 - 我仍在学习 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
将具有最后一次循环迭代的值.
当然,我知道我们可以通过定义一个函数来完成这一切,比如 fecthAndUnzip(URL,path)
。但我的问题与设计相关:这是我们在 Node 中可以做到的唯一方法,还是有更好的方法?例如,我可以访问 on('close')
事件中的文件名吗?如果可以,我应该访问吗?谢谢!
不知道是否对您有帮助,但是您在for循环中描述的问题有多种解决方案:
第一个,使用 let 而不是 var 将变量绑定到它的当前范围:
for (let i = 0; i < 4; i++) {
setTimeout(function() {
console.log('test 2', i);
}, 2000);
}
这将打印 0、1、2、3,即使循环将在调用第一个超时回调之前结束。
如果它是一个数组,你可以使用 forEach 而不是 for 循环
[0, 1, 2, 3].forEach(function(i) {
setTimeout(function() {
console.log('test 3', i);
}, 3000);
})
你可以使用外部函数:
for (var i = 0; i < 4; i++) {
setTimeout(function() {
logI(i);
}, 100);
}
function logI(i) {
console.log(i);
}
唯一重要的是你的变量需要绑定到一个内部范围以保持它的值,即使在你的异步函数被调用之前循环结束也是如此。
定义一个单独的函数绝对不是唯一的方法,还有更好的方法。
您没有显示完整的代码,但我认为由于您使用 var
定义变量的行为。如 var filename = 'something'
。执行此操作时,您是在全局 [function] 范围内定义文件名变量。这意味着无论它在哪里定义,函数的每个部分都可以使用它。在您的情况下,即使您在循环中定义了变量,它也在整个函数中起作用,所以每次迭代实际上都在覆盖该变量。
如果您想了解更多信息或者如果我解释得不够好,这里有一个关于作用域的很好的 Whosebug 答案:
解决方案是在当前块范围内定义一个变量。如果您使用的是实现 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,那么创建单独函数的原始答案可能是最好的解决方案。
如果我遗漏了什么,我很抱歉 - 我仍在学习 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
将具有最后一次循环迭代的值.
当然,我知道我们可以通过定义一个函数来完成这一切,比如 fecthAndUnzip(URL,path)
。但我的问题与设计相关:这是我们在 Node 中可以做到的唯一方法,还是有更好的方法?例如,我可以访问 on('close')
事件中的文件名吗?如果可以,我应该访问吗?谢谢!
不知道是否对您有帮助,但是您在for循环中描述的问题有多种解决方案:
第一个,使用 let 而不是 var 将变量绑定到它的当前范围:
for (let i = 0; i < 4; i++) {
setTimeout(function() {
console.log('test 2', i);
}, 2000);
}
这将打印 0、1、2、3,即使循环将在调用第一个超时回调之前结束。
如果它是一个数组,你可以使用 forEach 而不是 for 循环
[0, 1, 2, 3].forEach(function(i) {
setTimeout(function() {
console.log('test 3', i);
}, 3000);
})
你可以使用外部函数:
for (var i = 0; i < 4; i++) {
setTimeout(function() {
logI(i);
}, 100);
}
function logI(i) {
console.log(i);
}
唯一重要的是你的变量需要绑定到一个内部范围以保持它的值,即使在你的异步函数被调用之前循环结束也是如此。
定义一个单独的函数绝对不是唯一的方法,还有更好的方法。
您没有显示完整的代码,但我认为由于您使用 var
定义变量的行为。如 var filename = 'something'
。执行此操作时,您是在全局 [function] 范围内定义文件名变量。这意味着无论它在哪里定义,函数的每个部分都可以使用它。在您的情况下,即使您在循环中定义了变量,它也在整个函数中起作用,所以每次迭代实际上都在覆盖该变量。
如果您想了解更多信息或者如果我解释得不够好,这里有一个关于作用域的很好的 Whosebug 答案:
解决方案是在当前块范围内定义一个变量。如果您使用的是实现 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,那么创建单独函数的原始答案可能是最好的解决方案。