循环递增在传递给函数之前进行限制
我有一些代码来复制数组中包含的每个源目标和目标目录在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的范围。 在你的代码中,当你从mkdir
callback中查找的时候, 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
,它只是不容易的眼睛。