node.js - ¿Hay una mejor manera de escribir este método recursivo en TypeScript?
Estoy tratando de escribir un método para encontrar todos los archivos en una carpeta, incluyendo las subcarpetas. Es bastante simple de escribir usando fs.readdirSync, pero estoy tratando de escribir una versión que no bloquee. (es decir, que use fs.readdir).
Tengo una versión que funciona, pero no es bonita. ¿Puede alguien que tenga un poco más de experiencia con Node ver si hay una manera más agradable de escribir esto? Puedo ver algunos otros lugares en mi base de código donde puedo aplicar este patrón, ¡así que sería bueno tener una versión más limpia!
private static findFilesFromFolder(folder: string): Promise<string[]> {
let lstat = util.promisify(fs.lstat)
let readdir = util.promisify(fs.readdir)
// Read the initial folder
let files = readdir(folder)
// Join the folder name to the file name to make it absolute
.then(files => files.map(file => path.join(folder, file)))
// Get the stats for each file (also as a promise)
.then(files =>
Promise.all(files.map(file =>
lstat(file).then(stats => { return { file: file, stats: stats } })
))
)
// If the file is a folder, recurse. Otherwise just return the file itself.
.then(info =>
Promise.all(info.map(info => {
if (info.stats.isDirectory()) {
return this.findFilesFromFolder(info.file)
} else {
return Promise.resolve([info.file])
}
}
)))
// Do sume munging of the types - convert Promise<string[][]> to Promise<string[]>
.then(nested => Array.prototype.concat.apply([], nested) as string[])
return files
}
Respuesta #1
Haría algunas cosas para que esto esté más limpio:
- mover el caso base de la recursión desde dentro del bucle hasta el nivel superior
- usar la sintaxis
async/await - usa
consten lugar delet
También coloca las llamadas a promisify donde estás importando fs
const lstat = util.promisify(fs.lstat)
const readdir = util.promisify(fs.readdir)
…
private static async findFilesFromPath(folder: string): Promise<string[]> {
const stats = await lstat(folder);
// If the file is a folder, recurse. Otherwise just return the file itself.
if (stats.isDirectory()) {
// Read the initial folder
const files = await readdir(folder);
// Join the folder name to the file name to make it absolute
const paths = files.map(file => path.join(folder, file))
const nested = await Promise.all(paths.map(p => this.findFilesFromPath(p)))
// Do sume munging of the types - convert string[][] string[]
return Array.prototype.concat.apply([], nested) as string[];
} else {
return [folder];
}
}
