我有一些代码可以复制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
?
答案 0 :(得分:4)
你有一个经典问题是在异步函数上使用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');
}
});
});
}
归结为适当地确定变量范围。在您的i
回调中查看代码时,mkdir
的范围更广。 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
,这在眼睛上并不那么容易。