循环内的 NodeJS fs.stat
NodeJS fs.stat inside a loop
我遇到了一个奇怪的问题。我想这与节点异步工作的方式有关,但我不知道如何解决它。
我有以下代码:
function traverse(dir) {
console.log("START: " + dir);
fs.readdir(dir, function(err, list) {
list.forEach(function(element) {
path = dir + "/" + element
console.log("Loop files/folders : " + path);
fs.stat(path, function(err, stats,) {
console.log("fs.stats file path : " + path + " : " + stats.isDirectory())
});
}, this);
});
}
这给出了以下输出:
START: ./data/2017
Loop files/folders : ./data/2017/.DS_Store
Loop files/folders : ./data/2017/1
Loop files/folders : ./data/2017/2
Loop files/folders : ./data/2017/3
Loop files/folders : ./data/2017/Arendal2017.pptx
fs.stats file path : ./data/2017/Arendal2017.pptx : false
fs.stats file path : ./data/2017/Arendal2017.pptx : true
fs.stats file path : ./data/2017/Arendal2017.pptx : true
fs.stats file path : ./data/2017/Arendal2017.pptx : true
fs.stats file path : ./data/2017/Arendal2017.pptx : false
从代码中可以看出,首先我只是在循环中给出一个路径字符串的输出。然后,在同一个循环中,我为 director 中的每个路径(元素)做一个统计。这里发生的是当我在 fs.stat 回调中使用路径变量时,它指的是最后一个文件 "Arendal" 而不是循环中的每个单独的项目。根据文件和目录列表,isDirectory bool 实际上是正确的,但使用给定的 isDirectory bool 获得正确的路径对我来说也很重要..
如何解决?
这里的问题是您没有在正确的范围内声明 path
变量。
将代码更改为
list.forEach(function(element) {
var path = dir + "/" + element; // <=== DECLARE IT HERE
console.log("Loop files/folders : " + path);
fs.stat(path, function(err, stats,) {
console.log("fs.stats file path : " + path + " : " + stats.isDirectory())
});
}, this);
对于这种列表,假设它只是一个命令行实用程序,您可以通过简单地使用 fs
的同步函数(以便调用顺序保留在日志中)来获得更清晰的日志。
@Denys Séguret 回答了你的问题
只需添加两件事:
1/ 将异步代码放在循环中是一种不好的做法
2/ 因为你用的是node我猜它支持ES6(取决于你使用的版本)。试试吧!
try {
const stats = await Promise.all(list.map((element) => {
const path = `${dir}/${element}`;
console.log(`Loop files/folders : ${path}`);
return fs.stat(path);
}));
stats.forEach(x => console.log(`fs.stats file path : ${path} : ${stats.isDirectory()}`));
} catch (err) {
// Error handling
}
我遇到了一个奇怪的问题。我想这与节点异步工作的方式有关,但我不知道如何解决它。
我有以下代码:
function traverse(dir) {
console.log("START: " + dir);
fs.readdir(dir, function(err, list) {
list.forEach(function(element) {
path = dir + "/" + element
console.log("Loop files/folders : " + path);
fs.stat(path, function(err, stats,) {
console.log("fs.stats file path : " + path + " : " + stats.isDirectory())
});
}, this);
});
}
这给出了以下输出:
START: ./data/2017
Loop files/folders : ./data/2017/.DS_Store
Loop files/folders : ./data/2017/1
Loop files/folders : ./data/2017/2
Loop files/folders : ./data/2017/3
Loop files/folders : ./data/2017/Arendal2017.pptx
fs.stats file path : ./data/2017/Arendal2017.pptx : false
fs.stats file path : ./data/2017/Arendal2017.pptx : true
fs.stats file path : ./data/2017/Arendal2017.pptx : true
fs.stats file path : ./data/2017/Arendal2017.pptx : true
fs.stats file path : ./data/2017/Arendal2017.pptx : false
从代码中可以看出,首先我只是在循环中给出一个路径字符串的输出。然后,在同一个循环中,我为 director 中的每个路径(元素)做一个统计。这里发生的是当我在 fs.stat 回调中使用路径变量时,它指的是最后一个文件 "Arendal" 而不是循环中的每个单独的项目。根据文件和目录列表,isDirectory bool 实际上是正确的,但使用给定的 isDirectory bool 获得正确的路径对我来说也很重要..
如何解决?
这里的问题是您没有在正确的范围内声明 path
变量。
将代码更改为
list.forEach(function(element) {
var path = dir + "/" + element; // <=== DECLARE IT HERE
console.log("Loop files/folders : " + path);
fs.stat(path, function(err, stats,) {
console.log("fs.stats file path : " + path + " : " + stats.isDirectory())
});
}, this);
对于这种列表,假设它只是一个命令行实用程序,您可以通过简单地使用 fs
的同步函数(以便调用顺序保留在日志中)来获得更清晰的日志。
@Denys Séguret 回答了你的问题
只需添加两件事:
1/ 将异步代码放在循环中是一种不好的做法
2/ 因为你用的是node我猜它支持ES6(取决于你使用的版本)。试试吧!
try {
const stats = await Promise.all(list.map((element) => {
const path = `${dir}/${element}`;
console.log(`Loop files/folders : ${path}`);
return fs.stat(path);
}));
stats.forEach(x => console.log(`fs.stats file path : ${path} : ${stats.isDirectory()}`));
} catch (err) {
// Error handling
}