Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
517 views
in Technique[技术] by (71.8m points)

javascript - Await an iterative function without delimiter in JS

I've got a directory with an unknown amount of subfolders. Each subfolder might have or not further subfolders. I am itterating through them using a recursive function. Due to the unknown amounts of subfolders I am missing a way to make sure that all folders have been checked before I continue. My knowledge on async and await is quiet limited. Is there any Way to handle this problem?

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;
                }
            })
        }
    })
  }
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

You have a few options:

1) Since everything else is done using fs's synchronous methods, you could change fs.readdir to fs.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) Convert fs.readdirSync to a Promise and then use 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) Use a couple third-party modules to clean things up a bit (fs-extra takes care of promisifying asynchronous methods like fs.readdir for you. async-af provides chainable asynchronous JavaScript methods such as a 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});
    }
  });
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...