bluebird - 函数 returns 承诺对象而不是实际数据
bluebird - function returns promise objects instead of actual data
在 this snippet 之后,我正在尝试编写一个循环遍历目录、查找目录并从这些目录中读取 xml 文件名的函数(我知道文件夹结构将始终保持相同的)。到目前为止,我的函数按预期工作,但是当我尝试从函数中获取 return 时,我只获取了 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
中的最后一个 .then
函数中 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 } ]
为什么会发生这种情况以及如何解决?
试试这个
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))
...
将 return 一组对 then 回调的承诺。 promise 数组在这里算作立即值,不会被强制转换为数组的 Promise。要将 promise 数组转换为数组的 promise,您可以使用 Promise.all
,但由于您使用的是 bluebird,因此您有更好的选择:
你所要做的就是使用Promise.map
:
.then(function(directories) {
return Promise.map(directories, function(directory) {
return fs.readdirAsync(path.join(rootPath, directory))
...
行中
.then(function(directories) {
return directories.map(function(directory) {
return fs.readdirAsync…
您正在为一系列承诺创建承诺,而这正是您在最终日志中得到的内容。您需要 return 对值数组的承诺,而不是 return 承诺数组 - 而 Promise.all
正是这样做的:
.then(function(directories) {
return Promise.all(directories.map(function(directory) {
return fs.readdirAsync(…)
…
}));
})
但是,在 Bluebird 中,使用 Promise.map(directories, function(…) { … })
or even 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;
});
});
}
搞清楚了,有一个。然后第二个函数太多了:
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);
});
在 this snippet 之后,我正在尝试编写一个循环遍历目录、查找目录并从这些目录中读取 xml 文件名的函数(我知道文件夹结构将始终保持相同的)。到目前为止,我的函数按预期工作,但是当我尝试从函数中获取 return 时,我只获取了 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
中的最后一个 .then
函数中 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 } ]
为什么会发生这种情况以及如何解决?
试试这个
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))
...
将 return 一组对 then 回调的承诺。 promise 数组在这里算作立即值,不会被强制转换为数组的 Promise。要将 promise 数组转换为数组的 promise,您可以使用 Promise.all
,但由于您使用的是 bluebird,因此您有更好的选择:
你所要做的就是使用Promise.map
:
.then(function(directories) {
return Promise.map(directories, function(directory) {
return fs.readdirAsync(path.join(rootPath, directory))
...
行中
.then(function(directories) {
return directories.map(function(directory) {
return fs.readdirAsync…
您正在为一系列承诺创建承诺,而这正是您在最终日志中得到的内容。您需要 return 对值数组的承诺,而不是 return 承诺数组 - 而 Promise.all
正是这样做的:
.then(function(directories) {
return Promise.all(directories.map(function(directory) {
return fs.readdirAsync(…)
…
}));
})
但是,在 Bluebird 中,使用 Promise.map(directories, function(…) { … })
or even 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;
});
});
}
搞清楚了,有一个。然后第二个函数太多了:
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);
});