Javascript 节点承诺返回值为已解析承诺的对象

Javascript 节点承诺返回值为已解析承诺的对象,javascript,node.js,promise,bluebird,fs,Javascript,Node.js,Promise,Bluebird,Fs,我在下面有一些代码,它将返回目录中包含某些键和值的所有文件。我希望其中一个键是带有布尔值的isDirectory 下面的代码运行得很好,但我想知道是否有办法删除Promise.all/迭代promises,而将stat.isDirectory()的解析值直接推送到映射中的my files对象 我的解决方案我尝试过但失败: const Promise = require('bluebird'), os = require('os'), _ = require('lodash'),

我在下面有一些代码,它将返回目录中包含某些键和值的所有文件。我希望其中一个键是带有布尔值的isDirectory

下面的代码运行得很好,但我想知道是否有办法删除Promise.all/迭代promises,而将
stat.isDirectory()
的解析值直接推送到映射中的my files对象

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

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);
    })
我试过这样的方法:

isDirectory: fs.statAsync(path).then((stat) => stat.isDirectory())
然后在所有
isDirectory
键上执行承诺

工作代码:

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);
    })

到底有没有办法取消最后每个部分的承诺?而不是在我的映射中执行这些操作?

假设您使用的是最新的节点-您可以
async/wait
,将
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;

假设您使用的是最新的节点-您可以
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;

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

因为
map
是同步的,所以它不会等待
fs.statAsync
完成。但是您可以创建一个承诺数组
fs.statAsync
,该数组使用final files对象进行解析,只需使用
Promise.all
等待所有承诺完成即可

一个详细的版本,包含一些澄清意见:

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));

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

因为
map
是同步的,所以它不会等待
fs.statAsync
完成。但是您可以创建一个承诺数组
fs.statAsync
,该数组使用final files对象进行解析,只需使用
Promise.all
等待所有承诺完成即可

一个详细的版本,包含一些澄清意见:

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));