蓝鸟 – 函数返回承诺对象,而不是实际的数据

在这段代码之后,我试图编写一个函数,循环search目录,查找目录,并从这些目录中读取xml文件名(我知道文件夹结构将始终保持不变)。 到目前为止,我的function正在按预期工作,但是当我尝试从函数返回时,我只是得到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); }); 

当我在getFileNames的最后一个getFileNames函数内的console.log(files) ,我在控制台中得到了实际的文件名数组。 但是当我运行上面的代码时,我得到这个输出:

 [ 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 } ] 

为什么会发生这种情况,以及如何解决?

在线

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

你正在为一系列的承诺创造一个承诺,而这正是你在最终的日志中得到的。 你不需要返回一个promise数组,而是需要返回一个值数组的承诺 – Promise.all就是这样的:

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

然而,在Bluebird中,使用Promise.map(directories, function(…) { … })甚至是map方法会更加Promise.map(directories, function(…) { … })类似于你已经在每个目录中的文件中使用了.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; }); }); } 

尝试这个

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

这段代码:

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

将返回一个承诺数组到当时的callback。 承诺数组在这里算作立即数,不会被数组化为一个承诺。 要将Promise.all数组转换为数组的承诺,您可以使用Promise.all ,但是由于您使用的是蓝鸟,因此您有更好的select:

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

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

算出来,有一个。那么第二个函数太多了:

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