2016-03-07 47 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!對我來說愚蠢的錯誤。糾正。 –

相關問題