循环递增在传递给函数之前进行限制

我有一些代码来复制数组中包含的每个源目标和目标目录在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我的每个递增值?

你有一个经典的问题,因为for循环中使用一个asynchronous函数:循环在它调用的任何函数之前完成,所以当第一个函数实际开始做某事的时候,它引用的循环索引已经被覆盖。

使用.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'); } }); }); } 

归结为正确地确定variables的范围。 在你的代码中,当你从mkdircallback中查找的时候, i处于一个更高的范围内。 i的内容由for循环控制。 你想要一个本地数组索引。

您可以使用一个IIFEclosuresi并创build一个callback,它有它自己的副本:

 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 ,它只是不容易的眼睛。