2016-11-19 32 views
2

以下this snippet我想寫一個循環槽目錄,查找目錄,並從這些目錄中讀取XML文件名的函數(我知道文件夾結構將始終保持相同)。到目前爲止,我的函數按預期工作,但是當我試圖從函數返回時,我只是得到Promise對象。藍鳥 - 功能返回承諾對象,而不是實際數據

我的代碼:

const Promise = require('bluebird'); 
const fs = Promise.promisifyAll(require('fs')); 
const path = require('path'); 

function getFileNames(rootPath) { 
    // Read content of path 
    return fs.readdirAsync(rootPath) 
    // For every file in path 
    .then(function(directories) { 
     // Filter out the directories 
     return directories.filter(function(file) { 
     return fs.statSync(path.join(rootPath, file)).isDirectory(); 
     }); 
    }) 
    // For every directory 
    .then(function(directories) { 
     return directories.map(function(directory) { 
     // Read file in the directory 
     return fs.readdirAsync(path.join(rootPath, directory)) 
      .filter(function(file) { 
      return path.extname(file) == '.XML'; 
      }) 
      .then(function(files) { 
      // Do something with the files 
      return files; 
      }); 
     }); 
    }); 
} 

getFileNames('./XML').then(function(files) { 
    console.log(files); 
}); 

當我console.log(files)getFileNames最後.then函數中,我得到的文件名的實際陣列控制檯。但是,當我運行上面的代碼我得到這樣的輸出:

[ Promise { 
    _bitField: 0, 
    _fulfillmentHandler0: undefined, 
    _rejectionHandler0: undefined, 
    _promise0: undefined, 
    _receiver0: undefined }, 
    Promise { 
    _bitField: 0, 
    _fulfillmentHandler0: undefined, 
    _rejectionHandler0: undefined, 
    _promise0: undefined, 
    _receiver0: undefined }, 
    Promise { 
    _bitField: 0, 
    _fulfillmentHandler0: undefined, 
    _rejectionHandler0: undefined, 
    _promise0: undefined, 
    _receiver0: undefined }, 
    Promise { 
    _bitField: 0, 
    _fulfillmentHandler0: undefined, 
    _rejectionHandler0: undefined, 
    _promise0: undefined, 
    _receiver0: undefined }, 
    Promise { 
    _bitField: 0, 
    _fulfillmentHandler0: undefined, 
    _rejectionHandler0: undefined, 
    _promise0: undefined, 
    _receiver0: undefined } ] 

爲什麼會出現這種情況,如何解決?

回答

2

在行

.then(function(directories) { 
    return directories.map(function(directory) { 
    return fs.readdirAsync… 

您正在創建的承諾數組的承諾,這就是你在你最終的日誌得到什麼。而不是返回承諾的數組,你需要返回一個承諾的值的數組 - 和Promise.all恰恰是什麼:

.then(function(directories) { 
    return Promise.all(directories.map(function(directory) { 
    return fs.readdirAsync(…) 
    … 
    })); 
}) 

然而,在青鳥那將是更地道使用Promise.map(directories, function(…) { … })甚至the map method (類似於如何已經使用.filter在每個目錄中的文件一樣):

function getFileNames(rootPath) { 
    return fs.readdirAsync(rootPath) 
    .filter(function(file) { 
    return fs.statAsync(path.join(rootPath, file)).then(function(s) { 
     return s.isDirectory(); 
    }); 
    }) 
    .map(function(directory) { 
//^^^^ 
    return fs.readdirAsync(path.join(rootPath, directory)) 
    .filter(function(file) { 
     return path.extname(file) == '.XML'; 
    }) 
    .map(function(file) { 
     // Do something with every file 
     return file; 
    }); 
    }); 
} 
0

試試這個

return getFileNames('./XML').then(function(files) { 
    console.log(files); 
    return files; 
}); 
+0

stil得到相同的輸出 –

+0

@MihaŠušteršič我編輯answer – stasovlas

0

這段代碼:

.then(function(directories) { 
    return directories.map(function(directory) { 
    return fs.readdirAsync(path.join(rootPath, directory)) 
    ... 

將返回承諾的陣列,以當時的回調。承諾數組在這裏被視爲立即值,不會被集中到數組的承諾。爲了承諾數組轉換爲可以使用Promise.all數組的一個承諾,但由於使用的是藍鳥,你有更好的選擇:

所有你所要做的就是用Promise.map

.then(function(directories) { 
    return Promise.map(directories, function(directory) { 
    return fs.readdirAsync(path.join(rootPath, directory)) 
    ... 
0

想通了,有一個。後來太上第二個功能:

const Promise = require('bluebird'); 
const fs = Promise.promisifyAll(require('fs')); 
const path = require('path'); 

function getFileNames(rootPath) { 
    // Read content of path 
    return fs.readdirAsync(rootPath) 
     .then(function(content) { 
     return content.filter(function(file) { 
      return fs.statSync(path.join(rootPath, file)).isDirectory(); 
     }); 
     }) 
     // For every directory 
     .map(function(directory) { 
     // Read files in the directory 
     return fs.readdirAsync(path.join(rootPath, directory)) 
      .filter(function(file) { 
       return path.extname(file) == '.XML'; 
      }); 
     }); 
} 

getFileNames('./XML').then(function(files) { 
    console.log(files); 
});