是否有更好的方法在Typescript中编写此递归方法

时间:2019-12-10 12:14:48

标签: node.js typescript recursion promise

我正在尝试编写一种方法来查找文件夹中的所有文件,包括子文件夹。使用fs.readdirSync编写非常简单,但是我正在尝试编写一个不会阻塞的版本。 (即使用fs.readdir)。

我有一个可以使用的版本,但它并不漂亮。能对节点有更多经验的人可以看看是否有更好的方式编写此代码吗?我可以在代码库中看到其他一些可以应用此模式的地方,所以拥有一个更干净的版本会很不错!

  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
  }

1 个答案:

答案 0 :(得分:3)

我会做些事情来使它更清洁:

  • 将递归基础案例从循环内移动到顶层
  • 使用async / await语法
  • 使用const代替let

也将promisify呼叫放在您import正在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];
  }
}