NodeJS fs.stat在循环

时间:2017-08-24 14:46:04

标签: javascript node.js loops fs

我有一个我称之为奇怪的问题..我猜这与节点如何异步工作有关,但我无法弄清楚如何解决它..

我有以下代码:

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

从代码中可以看出,首先我只是给出循环中路径字符串的输出。然后,在同一个循环中,我为导演内的每个路径(元素)执行一个stat。这里发生的是当我在fs.stat回调中使用路径变量时,这指的是最后一个文件“Arendal”而不是循环中的每个单独项目。根据文件和目录列表,isDirectory bool实际上是正确的,但是对于我来说,使用给定的isDirectory bool获取正确的路径也很重要。

如何解决这个问题?

2 个答案:

答案 0 :(得分:4)

这里的问题是你没有在正确的范围内声明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的同步函数来获得更清晰的日志(以便调用的顺序保存在日志中)。

答案 1 :(得分:1)

@DenysSéguret回答了你的问题

只需添加两件事:

1 /将异步代码置于循环

中是一种不好的做法

2 /因为你使用节点我猜它支持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
}