javascript - For循环在传递给函数之前递增到限制

标签 javascript node.js for-loop closures fs

我有一些代码可以为 dirs 数组中的每个源目录和目标目录复制数组中包含的文件。通过循环的每次迭代,它都会调用复制的函数。它看起来像这样:

var filesInEachDir ["file1", "file2", "file3"];
var dirs = [
  {"source": "sourceDirectory1", "dest":"destinationDirectory1"},
  {"source": "sourceDirectory2", "dest":"destinationDirectory2"},
  {"source": "sourceDirectory3" "dest":"destinationDirectory3"},
];

for (var i = 0; i < dirs.length; i++){
  fs.mkdir(dirs[i], function(err){
    if(err){
      console.log(err);
    }else{
      copyFiles(dirs[i], filesInEachDir);
    }
   });
}

function copyFiles(dirs, files){
  for (var c = 0; c < files.length; c++){
    fs.copy(files[c], dirs.source, dirs.dest, {replace: false}, function(err){
      if (err){
        console.log(err);
      }else{
        console.log('file copied');
      }
    });
  }
}

由于某些原因,只有 dirs 的最后一个元素中的文件被复制。如果我将另一个元素添加到 dirs,它的文件将被复制,而不是任何其他元素。所以看起来 i 在调用 copyFiles 函数之前完全递增。为什么会这样?如何为 copyFiles 提供 i 的每个增量值?

最佳答案

您遇到了在异步函数上使用 for 循环引起的经典问题:循环在它调用的任何函数完成之前很久就结束了,所以当第一个函数真正开始做某事时,它引用的循环索引已被覆盖。

改用 .forEach 以避免覆盖循环索引。

var filesInEachDir = ["file1", "file2", "file3"];
var dirs = [
  {"source": "sourceDirectory1", "dest":"destinationDirectory1"},
  {"source": "sourceDirectory2", "dest":"destinationDirectory2"},
  {"source": "sourceDirectory3", "dest":"destinationDirectory3"}
];

dirs.forEach(function (dir) {
  fs.mkdir(dir, function(err) {
    if (err) {
      console.log(err);
    } else {
      copyFiles(dir, filesInEachDir);
    }
  });
});

function copyFiles(dir, files) {
  files.forEach(function (file) {
    fs.copy(file, dir.source, dir.dest, {replace: false}, function(err) {
      if (err) {
        console.log(err);
      } else {
        console.log('file copied');
      }
    });
  });
}

它归结为正确地确定变量的范围。在您的代码中,从 mkdir 回调中查看时, i 处于更高范围。 i 的内容由 for 循环从外部控制。您需要一个本地 数组索引。

您可以使用 IIFE关闭 i 并创建一个回调,它有自己的副本:

for (var i = 0; i < dirs.length; i++){
  fs.mkdir(dir, (function (i) {
    return function(err) {
      if (err) {
        console.log(err);
      } else {
        copyFiles(dirs[i], filesInEachDir);
      }
    };
  })(i));
}

或者更好

for (var i = 0; i < dirs.length; i++){
  fs.mkdir(dir, (function (dir) {
    return function(err) {
      if (err) {
        console.log(err);
      } else {
        copyFiles(dir, filesInEachDir);
      }
    };
  })(dirs[i]));
}

...这在技术上等同于使用 .forEach,只是看起来不那么容易。

关于javascript - For循环在传递给函数之前递增到限制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31575009/

相关文章:

c++ - for 循环帮助。在不应该的时候终止。 C++

javascript - 无法通过单击将 css 属性添加到 <td> 元素

javascript - Node js和mysql将带逗号的数字转换为 float

javascript - safari&IE中链接形状坐标浏览器

javascript - 我可以使用 pactjs 来测试通过事件流和消息队列进行通信的微服务吗?

node.js - Cordova Apache错误的模块路径

css - 内部带有for循环的SCSS函数不起作用

javascript - 在 JavaScript 的 for 循环中获取隐藏的输入值

javascript - 光学变焦禁用

Javascript - FileReader 如何一次读取和处理多个文件中的每个文件