如何一次处理多个承诺

问题描述 投票:0回答:1

我正在创建一个程序...

1.检查任何给定系统上的所有驱动器。

2.扫描那些驱动器以查找特定文件类型的文件。例如,它可能会在所有驱动器中搜索任何jpegpngsvg文件。

3.将结果存储在以下格式的JSON文件中。

{
  "C:": {
    "jpeg": [
      ...
      {
        "path": "C:\\Users\\John\\Pictures\\example.jpeg",
        "name": "example",
        "type": "jpeg",
        "size": 86016
      },
      ...
    ],
    "png": [],
    "svg": []
  },
  ...
}

代码...

async function scan(path, exts) {
  try {
    const stats = await fsp.stat(path)
    if (stats.isDirectory()) {
      const
        childPaths = await fsp.readdir(path),
        promises = childPaths.map( 
          childPath => scan(join(path, childPath), exts)
        ),
        results = await Promise.all(promises)


      // Likely needs to change.
      return [].concat(...results)


    } else if (stats.isFile()) {
      const fileExt = extname(path).replace('.', '')
      if (exts.includes(fileExt)){


        // Likely needs to change.
        return {
          "path": path,
          "name": basename(path, fileExt).slice(0, -1),
          "type": fileExt,
          "size": stats.size
        }


      }
    }
    return []
  }
  catch (error) {
    return []
  }
}


const results = await Promise.all(
  config.drives.map(drive => scan(drive, exts))
)

console.log(results) // [ Array(140), Array(0), ... ]

// And I would like to do something like the following...

for (const drive of results) {
  const
    root = parse(path).root,
    fileExt = extname(path).replace('.', '')
  data[root][fileExt] = []
}

await fsp.writeFile('./data.json', JSON.stringify(config, null, 2))

全局results当然分为与每个驱动器相对应的单个数组。但是目前,尽管它们具有相应的文件类型,但它会将所有对象组合成一个巨型数组。目前也没有办法让我知道每个驱动器属于哪个阵列,特别是如果驱动器的阵列不包含我可以解析以检索根目录的任何项目。

我显然可以再次将map设置为全局results,并按其type属性值对这些对象进行排序,但是让scan()从一开始就处理所有内容将更加干净。

由于缺乏异步性和对象方面的经验,因此我不确定如何最好地处理map( ... ) / scan中的数据。我真的甚至不确定如何最好地构造scan()的输出,以便易于操作全局results的结构。

任何帮助将不胜感激。

javascript node.js asynchronous promise fs
1个回答
1
投票

这实际上可以解决问题,但我实际上无法测试这一巨大警告。

// This should get you an object with one property per drive
const results = Object.fromEntries(
  (
    await Promise.all(
      config.drives.map(drive => [drive, scan(drive, exts)])
    )
  )
  .map(
    [drive, files] => [
      drive,
      // we reduce each drive's file array to an object with
      // one property per file extension
      files.reduce(
        (file) => {
          acc[file.type].push(file)
          return acc
        },
        Object.fromEntries(exts.map(ext => [ext, []]))
      )
    ]
  )
)

如果您不控制节点版本,或者您使用的版本尚不支持Object.fromEntries(),我们将需要对其进行填充或编写。

© www.soinside.com 2019 - 2024. All rights reserved.