一尘不染

等待JS中没有分隔符的迭代函数

json

我有一个目录,其中包含未知数量的子文件夹。每个子文件夹可能具有或没有其他子文件夹。我正在使用递归函数来遍历它们。由于子文件夹数量不明,我没有一种方法来确保在继续之前检查所有文件夹。我对异步和等待的了解非常有限。有什么办法可以解决这个问题?

function searchForPackage(directory){
    fs.readdir(directory, function(err, files){
        if(err){
            return;
        }else{
            files.forEach(file => {
                var currentLocation = directory + "/" + file;
                if(fs.statSync(currentLocation).isDirectory() && file != 'bin' && file != '.bin'){
                    searchForPackage(currentLocation);
                    return;
                }else if(file == "package.json"){
                    var content = fs.readFileSync(currentLocation);
                    var jsonContent = JSON.parse(content);
                    var obj = {
                        name: jsonContent.name,
                        license: jsonContent.license,
                        version: jsonContent.version
                    }
                    jsonTable.push(obj);
                    jsonTable.push({name: jsonContent.name, license: jsonContent.license, version: jsonContent.version});
                    return;
                }
            })
        }
    })
  }

阅读 240

收藏
2020-07-27

共1个答案

一尘不染

您有几种选择:

1)由于其他所有操作都使用fs的同步方法完成,因此您可以更改fs.readdirfs.readdirSync

function searchForPackage(directory) {
  fs.readdirSync(directory).forEach(file => {
    var currentLocation = directory + "/" + file;
    if (fs.statSync(currentLocation).isDirectory() && file != 'bin' && file != '.bin') {
      searchForPackage(currentLocation);
      return;
    } else if (file == "package.json") {
      var content = fs.readFileSync(currentLocation);
      var jsonContent = JSON.parse(content);
      var obj = {
        name: jsonContent.name,
        license: jsonContent.license,
        version: jsonContent.version
      }
      jsonTable.push(obj);
      jsonTable.push({name: jsonContent.name, license: jsonContent.license, version: jsonContent.version});
      return;
    }
  })
}

2)转换fs.readdirSync为a Promise然后使用async/await

async function searchForPackage(directory) {
  const files = await new Promise((resolve, reject) => {
    fs.readdir(directory, (err, files) => {
      if (err) reject(err);
      else resolve(files);
    });
  });
  await Promise.all(files.map(async file => {
    var currentLocation = directory + "/" + file;
    if (fs.statSync(currentLocation).isDirectory() && file != 'bin' && file != '.bin') {
      await searchForPackage(currentLocation);
      return;
    } else if (file == "package.json") {
      var content = fs.readFileSync(currentLocation);
      var jsonContent = JSON.parse(content);
      var obj = {
        name: jsonContent.name,
        license: jsonContent.license,
        version: jsonContent.version
      }
      jsonTable.push(obj);
      jsonTable.push({name: jsonContent.name, license: jsonContent.license, version: jsonContent.version});
      return;
    }
  }))
}

3)使用几个第三方模块来进行一些清理(fs-extra照顾像fs.readdir您一样的异步方法。async- af提供可链接的异步JavaScript方法,例如parallel
forEach。):

const fs = require('fs-extra');
const AsyncAF = require('async-af');

async function searchForPackage(directory) {
  await AsyncAF(fs.readdir(directory)).forEach(async file => {
    var currentLocation = directory + "/" + file;
    if (fs.statSync(currentLocation).isDirectory() && file != 'bin' && file != '.bin') {
      await searchForPackage(currentLocation);
    } else if (file == "package.json") {
      var content = fs.readFileSync(currentLocation);
      var jsonContent = JSON.parse(content);
      var obj = {
        name: jsonContent.name,
        license: jsonContent.license,
        version: jsonContent.version
      }
      jsonTable.push(obj);
      jsonTable.push({name: jsonContent.name, license: jsonContent.license, version: jsonContent.version});
    }
  });
}
2020-07-27