我有一个目录,其中包含未知数量的子文件夹。每个子文件夹可能具有或没有其他子文件夹。我正在使用递归函数来遍历它们。由于子文件夹数量不明,我没有一种方法来确保在继续之前检查所有文件夹。我对异步和等待的了解非常有限。有什么办法可以解决这个问题?
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; } }) } }) }
您有几种选择:
1)由于其他所有操作都使用fs的同步方法完成,因此您可以更改fs.readdir为fs.readdirSync:
fs
fs.readdir
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)转换fs.readdirSync为a Promise然后使用async/await:
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。):
fs-extra
async- af
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}); } }); }