【问题标题】:Node Promise return object with value of resolved promise节点承诺返回对象,其值为已解决的承诺
【发布时间】:2017-07-18 06:34:35
【问题描述】:

我下面有一些代码将返回目录中具有特定键和值的所有文件。我想成为的键之一是带有布尔值的 isDirectory。

下面的代码工作得很好,但我想知道是否有办法删除 Promise.all/iteration over promises,而是直接在我的地图中将 stat.isDirectory() 的解析值推送到我的文件对象。

我尝试过但失败的解决方案:

我尝试过这样的事情:

isDirectory: fs.statAsync(path).then((stat) => stat.isDirectory())

然后对所有 isDirectory 键执行 Promise.all

工作代码:

const Promise = require('bluebird'),
    os = require('os'),
    _ = require('lodash'),
    fs = Promise.promisifyAll(require('fs')),
    desktopPath = `${os.homedir()}/Desktop`;

let files = [];

return fs.readdirAsync(desktopPath)
    .then((filesName) => files = _.map(filesName, (fileName) => ({
        path: `${desktopPath}/${fileName}`,
        name: fileName,
        ext: _.last(fileName.split('.'))
    })))
    .then(() => Promise.all(_.map(files, (file) => fs.statAsync(file.path))))
    .then((stats) => _.forEach(stats, (stat, idx) => {
        files[idx].isDirectory = stat.isDirectory();
    }))
    .then(() => {
        console.log(files);
    })

到底有没有删除 Promise.all 和 _.forEach 部分?而是在我的地图中执行这些操作?

【问题讨论】:

    标签: javascript node.js promise bluebird fs


    【解决方案1】:

    您不能完全删除Promise.all,因为您希望等待所有文件完成后再使用最终结果。但是您可以在一个 .then() 电话中完成所有操作。

    因为map 是同步的,所以它不会等待fs.statAsync 完成。但是你可以创建一个fs.statAsync 的promise 数组,这些promise 使用最终的文件对象进行解析,然后使用Promise.all 等待它们全部完成。

    一个详细的版本,其中包含一些用于澄清的 cmets:

    fs.readdirAsync(desktopPath)
      .then(fileNames => {
        // Array of promises for fs.statAsync
        const statPromises = fileNames.map(fileName => {
          const path = `${desktopPath}/${fileName}`;
          // Return the final file objects in the promise
          return fs.statAsync(path).then(stat => ({
            path,
            name: fileName,
            ext: _.last(fileName.split(".")),
            isDirectory: stat.isDirectory()
          }));
        });
        // Promise.all to wait for all files to finish
        return Promise.all(statPromises);
      })
      .then(finalFiles => console.log(finalFiles));
    

    还有精简版:

    fs.readdirAsync(desktopPath)
      .then(fileNames => Promise.all(
        fileNames.map(fileName =>
          fs.statAsync(`${desktopPath}/${fileName}`).then(stat => ({
            path: `${desktopPath}/${fileName}`,
            name: fileName,
            ext: _.last(fileName.split(".")),
            isDirectory: stat.isDirectory()
          })))
      ))
      .then(finalFiles => console.log(finalFiles));
    

    【讨论】:

      【解决方案2】:

      假设您使用的是最新的 Node - 您可以 async/await,将 async 放在您的函数定义之前并执行以下操作:

      const fileNames = await fs.readdirAsync(desktopPath);
      const files = await Promise.map(fileNames, fileName => Promise.props({
        path: `${desktopPath}/${fileName}`,
        name: fileName,
        ext: fileName.split('.').pop(),
        isDirectory: fs.statAsync(`${desktopPath}/${fileName}`);
      })));
      console.log(files);
      return files;
      

      【讨论】:

        猜你喜欢
        • 2021-05-25
        • 2013-05-15
        • 1970-01-01
        • 1970-01-01
        • 2022-01-18
        • 1970-01-01
        • 2018-04-02
        • 2020-01-04
        • 1970-01-01
        相关资源
        最近更新 更多