return 在 Array.forEach 块中的所有承诺都已解决之后
return after all promises in Array.forEach block has been resolved
我在一个类似于 npm page of es6-promisify 上的示例的简单示例中尝试 nodejs 中的 es6-promisify 模块。
但我想使用 forEach 循环来检查条目的统计信息,如果它们是目录,则将它们推送到单独的数组:
var fs=require('fs');
var promisify=require('es6-promisify');
var path='../test_folder/';
function listSubfolderNamesSync(fpath){
var arrayOfFolders=[];
var array=fs.readdirSync(fpath);
array.forEach(function(element,index,array){
var stat=promisify(fs.stat);
stat(path+element).then(function(stats){
if (stats.isDirectory()){
arrayOfFolders.push(element);
console.log('pushed');
}
})
});
return arrayOfFolders;
}
console.log(listSubfolderNamesSync(path));
如果有 2 个子文件夹,输出将是:
[]
pushed
pushed
我知道为什么我的代码不能按我想要的方式运行,但我不知道如何优雅地解决这个问题。我已经看到带有 Promise.all()
的代码示例和 Array.map()
的用法来获得一系列承诺并等待所有承诺在链中前进之前解决。我看到的问题是,我t/don不想在每次检查统计数据时显式地创建一个承诺,并将这些承诺放在一个数组中以供使用 Promise.all(array)
。我觉得该解决方案需要相当多的变通方法,并且会大大降低代码的可读性。
也许最好只在 forEach 循环中使用它,这是我在尝试承诺之前的工作代码:
if(fs.statSync(path+element).isDirectory()){
arrayOfFolders.push(element);
}
可能是我编程经验不足的缘故,但是好像promises、callback和synchronous code混在一起,并没有书上写的那么简单?
作为 stat()
returns 的承诺,您的 listSubfolderNamesSync()
功能也必须如此,使其成为 listSubfolderNamesAsync()
。除非 stat()
的同步替代方案可用,否则这是不可避免的。
在 listSubfolderNamesAsync()
中,您需要将 fs.readdirSync()
返回的数组映射到一个承诺数组,然后使用 Promise.all()
将这些承诺(及其传递的数据)聚合到一个承诺。
var fs = require('fs');
var promisify = require('es6-promisify');
var stat = promisify(fs.stat);
var path = '../test_folder/';
function listSubfolderNamesAsync(fpath) {
var promises = fs.readdirSync(fpath).map(function(element) {
return stat(path + element).then(function(stats) {
return stats.isDirectory() ? element : null;
});
});
return Promise.all(promises).then(function(results) {
return results.filter(function(res) {
return res !== null;
});
});
}
现在用 .then()
处理结果:
listSubfolderNamesAsync(path).then(function(folders) {
console.log(folders);
});
使用 returns 分隔文件夹列表 和 文件的更通用的功能并没有太大的性能损失。你可以这样写:
function listSubElementsAsync(fpath) {
var promises = fs.readdirSync(fpath).map(function(element) {
return stat(path + element).then(function(stats) {
var type = stats.isDirectory() ? 'folder' : 'file';
return {type:type, element:element};
});
});
return Promise.all(promises).then(function(results) {
var files = results.filter(obj => obj.type === 'file').map(obj => obj.element);
var folders = results.filter(obj => obj.type === 'folder').map(obj => obj.element);
return {files:files, folders:folders};
});
}
listSubElementsAsync(path).then(function(list) {
console.log(list.files);
console.log(list.folders);
});
我在一个类似于 npm page of es6-promisify 上的示例的简单示例中尝试 nodejs 中的 es6-promisify 模块。 但我想使用 forEach 循环来检查条目的统计信息,如果它们是目录,则将它们推送到单独的数组:
var fs=require('fs');
var promisify=require('es6-promisify');
var path='../test_folder/';
function listSubfolderNamesSync(fpath){
var arrayOfFolders=[];
var array=fs.readdirSync(fpath);
array.forEach(function(element,index,array){
var stat=promisify(fs.stat);
stat(path+element).then(function(stats){
if (stats.isDirectory()){
arrayOfFolders.push(element);
console.log('pushed');
}
})
});
return arrayOfFolders;
}
console.log(listSubfolderNamesSync(path));
如果有 2 个子文件夹,输出将是:
[]
pushed
pushed
我知道为什么我的代码不能按我想要的方式运行,但我不知道如何优雅地解决这个问题。我已经看到带有 Promise.all()
的代码示例和 Array.map()
的用法来获得一系列承诺并等待所有承诺在链中前进之前解决。我看到的问题是,我t/don不想在每次检查统计数据时显式地创建一个承诺,并将这些承诺放在一个数组中以供使用 Promise.all(array)
。我觉得该解决方案需要相当多的变通方法,并且会大大降低代码的可读性。
也许最好只在 forEach 循环中使用它,这是我在尝试承诺之前的工作代码:
if(fs.statSync(path+element).isDirectory()){
arrayOfFolders.push(element);
}
可能是我编程经验不足的缘故,但是好像promises、callback和synchronous code混在一起,并没有书上写的那么简单?
作为 stat()
returns 的承诺,您的 listSubfolderNamesSync()
功能也必须如此,使其成为 listSubfolderNamesAsync()
。除非 stat()
的同步替代方案可用,否则这是不可避免的。
在 listSubfolderNamesAsync()
中,您需要将 fs.readdirSync()
返回的数组映射到一个承诺数组,然后使用 Promise.all()
将这些承诺(及其传递的数据)聚合到一个承诺。
var fs = require('fs');
var promisify = require('es6-promisify');
var stat = promisify(fs.stat);
var path = '../test_folder/';
function listSubfolderNamesAsync(fpath) {
var promises = fs.readdirSync(fpath).map(function(element) {
return stat(path + element).then(function(stats) {
return stats.isDirectory() ? element : null;
});
});
return Promise.all(promises).then(function(results) {
return results.filter(function(res) {
return res !== null;
});
});
}
现在用 .then()
处理结果:
listSubfolderNamesAsync(path).then(function(folders) {
console.log(folders);
});
使用 returns 分隔文件夹列表 和 文件的更通用的功能并没有太大的性能损失。你可以这样写:
function listSubElementsAsync(fpath) {
var promises = fs.readdirSync(fpath).map(function(element) {
return stat(path + element).then(function(stats) {
var type = stats.isDirectory() ? 'folder' : 'file';
return {type:type, element:element};
});
});
return Promise.all(promises).then(function(results) {
var files = results.filter(obj => obj.type === 'file').map(obj => obj.element);
var folders = results.filter(obj => obj.type === 'folder').map(obj => obj.element);
return {files:files, folders:folders};
});
}
listSubElementsAsync(path).then(function(list) {
console.log(list.files);
console.log(list.folders);
});