const fs = require('fs').promises;
async function readMe(folder) {
let result = [];
try {
const content = await fs.readdir(folder, { withFileTypes: true });
for (let item of content) {
if (item.isDirectory()) {
await readMe(`${folder}/${item.name}`);
} else {
if (item.name === "sales.json") {
result.push(`${folder}/${item.name}`);
}
}
}
} catch (err) {
console.log(err);
}
return result;
}
async function main() {
const results = await readMe("stores");
console.log(results);
}
main();
我试图列出“stores”文件夹的目录和子目录中 sales.json 的路径。我很困惑为什么上面的代码没有给出预期的结果。 在 if 语句中更改为这一行时:
result.push(... await readMe(`${folder}/${item.name}`) )
使代码正常工作。 如果我在目录和子目录中遇到任何 sales.json 文件,我会在 else 语句中处理路径。那么为什么我还需要再次将其推入 if 语句中?
避免混合关注点以提高代码的可重用性。编写一个简单的
ls
来递归生成所有路径 -
import { readdir } from "fs/promises"
import { basename, join } from "path"
async function* ls(path = ".") {
yield path
for (const dirent of await readdir(path, { withFileTypes: true }))
if (dirent.isDirectory())
yield* ls(join(path, dirent.name))
else
yield join(path, dirent.name)
}
从
find
-派生
ls
async function* find(path = ".", query) {
for await (const f of ls(path))
if (query(f) === true)
yield f
}
使用
find
和 Array.fromAsync
得出结果 -
Array.fromAsync(
search(".", f => basename(f) == "sales.json")
)
.then(console.log, console.error)
发电机可以暂停和恢复。这意味着如果可以尽早确定答案,我们可以避免做不必要的工作。如果我们只想要 first
sales.json
文件 -
async function findSalesJson(path = ".") {
for await (const f of search(path, f => basename(f) == "sales.json"))
return f
throw Error("sales.json not found")
}
findSalesJson(".")
.then(path => console.log("found sales.json at", path))
.catch(console.error)
有关使用异步生成器的更多说明和其他方法,请参阅此问答。