请求和写入流文件名

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 是一个常见的问题,当使用异步函数并发现 ii 的最后一个值时变得困惑。

如果你不使用 ES6,你可以在每个循环中定义一个匿名函数:

for (var i = 0; i < files.length; i++) {
  var filename = files[i];
  (function (file) {
    // Do stuff
  })(filename);
}

这与您描述的解决方案相同,只是您是动态创建和执行函数。如果您出于某种原因不使用 ES6,那么创建单独函数的原始答案可能是最好的解决方案。