【发布时间】:2017-05-09 11:44:26
【问题描述】:
目标
我在一个数组中有一堆文件名,并且想读取第一个存在的文件的内容。它们是配置文件,所以顺序是确定性的很重要,所以我不能使用.race()。我在下面的版本按顺序映射每个文件,尝试加载它,如果加载成功,调用resolve。
问题
以下是此实现的几个问题:
- 调用
resolve(...)并不会真正退出循环,因此程序会打开列表中的每个文件,即使在不需要时也是如此。 - 拒绝条件(
this is required to reject when we don't receive any files)似乎是一个 hack。但是,如果它不在这里,则承诺永远不会被拒绝。 - 解析代码看起来有点像 promise 反模式。
有没有更好的方法来构建这个?我可能可以通过一个Promise.filter 调用来做到这一点,但如果我不需要,我不想查询每个文件。
谢谢
代码
var Promise = require('bluebird');
var fs = Promise.promisifyAll(require('fs'));
var _ = require('lodash');
new Promise((resolve, reject) => {
// Resolve with the first of the files below that exists
return Promise.mapSeries(
['./file_that_doesntexist.json', '../file_that_might_exist.json', './file_that_doesnt_exist_either.json', '../file_that_exists.json']
, (filename) => fs.readFileAsync(filename, 'utf-8')
.then(file => {
resolve([filename, file]);
return true;
})
.catch(_.stubFalse)
)
.then(files => { // this is required to reject when we don't receive any files
if(!files.some(x => x))
reject('did not receive any files');
});
})
.then(function([filename, configFile]) {
// do something with filename and configFile
})
.catch(function(err) {
console.error(err)
})
【问题讨论】:
-
您可以尝试在 Promise 中使用 for...in 循环,然后在成功找到第一个文件时跳出循环。
标签: javascript promise bluebird