2016-03-07 52 views
0

我正在尝试nodejs中的es6-promisify模块,其操作步骤类似于npm page of es6-promisify上的示例。 但我想使用foreach循环检查条目的统计数据和他们推到一个单独的数组,如果他们是目录:返回Array.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()的用法有一系列的承诺,并等待它们全部解决之后再继续下去。我看到的问题是,我无法/不想在每次检查统计信息时明确地创建一个承诺,并将这些承诺放入数组中以使用Promise.all(array)。我感觉解决方案需要相当的解决方法,并会大大降低代码的可读性。 也许这只是为了更好地在foreach循环,这是我工作的代码之前,我想尝试promisify使用:

if(fs.statSync(path+element).isDirectory()){ 
     arrayOfFolders.push(element); 
} 

也许这是因为我缺乏编程经验,但它似乎是混合承诺,回调和同步代码不像书中写的那么简单?

+2

不,'Promise.all' +'map'是唯一合适的解决方案。尝试一下! – Bergi

回答

1

由于stat()返回一个承诺,所以你的listSubfolderNamesSync()函数,使其listSubfolderNamesAsync()。除非有与stat()同步的替代方案,否则这是不可避免的。

里面listSubfolderNamesAsync(),则需要通过fs.readdirSync()回到承诺的阵列阵图,然后用Promise.all()那些承诺(和他们提供的数据)aggregatge成一个单一的承诺。

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

有一个在具有返回文件夹文件的单独列表更通用的功能没有太大的性能损失。你可以这样写:

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

感谢您的详细解答,它可以帮助您!这是我正在寻找的那种答案。只有一个小问题:fs.stat()。isDirectory返回一个布尔值,而不是像你的代码示例那样的字符串。对于试验你的代码并想知道空阵列的人们。 –

+0

Doh!对我来说愚蠢的错误。纠正。 –