[英]Node Promise return object with value of resolved promise
I have some code below that will return all files in a directory with certain keys and values. 我下面有一些代码,这些代码将返回具有某些键和值的目录中的所有文件。 One of those keys I want to be isDirectory with a boolean value.
我想成为的键之一是具有布尔值的isDirectory。
The code below works just fine, but I was wondering if there was a way to remove the Promise.all/iterating over promises and instead pushing the resolved value of the stat.isDirectory()
to my files objects directly in my map. 下面的代码工作正常,但是我想知道是否有一种方法可以删除Promise.all /迭代promise,而是将
stat.isDirectory()
的解析值直接推到我的地图中的文件对象中。
My solution I tried but failed: 我尝试但失败的解决方案:
I tried something like this: 我尝试过这样的事情:
isDirectory: fs.statAsync(path).then((stat) => stat.isDirectory())
And then do a Promise.all on all the isDirectory
keys 然后对所有
isDirectory
键执行Promise.all
Working Code: 工作代码:
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);
})
Is there anyway to remove the Promise.all and _.forEach part at the end? 无论如何,最后是否要删除Promise.all和_.forEach部分? And instead do those actions in my map?
而是在我的地图中执行了这些操作?
You cannot remove the Promise.all
entirely, because you want to wait for all files to finish before you use the final result. 您不能完全删除
Promise.all
,因为您要等待所有文件完成后才能使用最终结果。 But you can do it all in one .then()
call. 但是您可以在一个
.then()
调用中完成全部操作。
Because map
is synchronous, it won't wait for the fs.statAsync
to finish. 因为
map
是同步的,所以它不会等待fs.statAsync
完成。 But you can create an array of promises of fs.statAsync
that resolve with the final files object and the simply wait for all of them to complete by using Promise.all
. 但是,您可以创建一个由
fs.statAsync
组成的承诺数组,这些承诺将与最终文件对象一起解析,并通过使用Promise.all
来简单地等待所有这些对象完成。
A verbose version with some comments for clarification: 带有一些注释的详细版本:
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));
And the compact version: 精简版:
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));
Assuming you're using the latest Node - you can async/await
, put async
before your function definition and do: 假设您使用的是最新的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;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.