Javascript 蓝知更鸟承诺。有什么提前拒绝的吗?

Javascript 蓝知更鸟承诺。有什么提前拒绝的吗?,javascript,promise,bluebird,Javascript,Promise,Bluebird,我在所有Node.js项目中都使用promise library Bluebird。为了从文件路径列表中获取第一个存在的文件的内容,我使用了Promise。任何都成功地如下所示: Promise.any([ './foo/file1.yaml', './foo/file2.yaml', './foo/file3.yaml' ], function(filePath) { _readFile(filePath); }),then(function(fileContent)

我在所有Node.js项目中都使用promise library Bluebird。为了从文件路径列表中获取第一个存在的文件的内容,我使用了
Promise。任何
都成功地如下所示:

Promise.any([
   './foo/file1.yaml',
   './foo/file2.yaml',
   './foo/file3.yaml'
], function(filePath) {
    _readFile(filePath);
}),then(function(fileContent) {
    _console.log(fileContent);
});
我的问题是,如果在读取文件时遇到与“未找到文件”不同的错误,如何提前退出
Promis.any
循环?以下代码说明了我的问题:

Promise.any([
   './foo/file1.yaml',
   './foo/file2.yaml',
   './foo/file3.yaml'
], function(filePath) {
    _readFile(filePath)
    .catch(function(err) {
       var res = err;
       if (err.code == FILE_NOT_FOUND) {
          // continue the Promise.any loop
       } else {
          // leave the Promise.any loop with this error
          err = new Promise.EarlyBreak(err);
       }
       Promise.reject(err);
    });
}).then(function(fileContent) {
    _console.log(fileContent);
}, function(err) {
    // the first error different from FILE_NOT_FOUND
});

可能是
Promise。any
不是正确的函数?

留下一个
Promise。any()
早期循环在概念上是有问题的,因为
Promise。any()
是一个聚合器,而不是一个循环,它接受一系列承诺,每个承诺都有自己的生命,而不是由
Promise.any()
决定的

但是,从路径数组开始,可以将您搜索的循环表示为
路径.reduce(…)
表达式,它直接构建了
.catch()
链,如下所示:

function getFirstGoodFileContent(paths) {
    paths.reduce(function(promise, path) {
        return promise.catch(function() {
            return _readFile(path);
        });
    }, Promise.reject()); // seed the chain with a rejected promise.
}
:信用卡

这样构建的.catch链在失败时将前进到下一个迭代,或者在成功时跳到链的末尾。这种流量控制与更正常的“然后”链(以实现的承诺为种子)中发生的情况相反

但这还不是全部。需要一个额外的条件,即“如果我遇到与“未找到文件”不同的错误,请提前离开[Promise.any]循环”。通过发送成功路径中除“未找到文件”之外的所有错误,这非常简单地被设计到捕获链中,因此:

  • 影响所需的流量控制(跳过链的其余部分),但是
  • 在成功的过程中,最终会出现一个错误条件-不希望出现,但可以恢复
因此,您现在可以拨打:

getFirstGoodFileContent([
    './foo/file1.yaml',
    './foo/file2.yaml',
    './foo/file3.yaml'
]).then(function(fileContent) {
    _console.log(fileContent);
}, function(error) {
    // error will be due to :
    // * a non-FILE_NOT_FOUND error having occurred, or
    // * the final path having resulted in an error.
    console.log(error); 
});

我在我所有的项目中也使用蓝鸟,但从未尝试过类似的方法。这只是一个未经测试的想法,但您是否可以设置一个变量,如var-isErr,如果达到早期中断场景,您可以将其设置为true。然后在您的其他承诺中设置一个重复计时器来检查该var的状态,如果为真,则拒绝?不会立即退出,但可能会很快退出。呃,
承诺。有没有不接受回调的?反正也没有“循环”,它们是并行等待的?我建议您使用
reduce
或递归手动编写。是的,您是对的<代码>承诺。任何
都不会接受回调。我希望按顺序检查文件,并且下一个仅当prevoius不存在时才检查。在所有其他情况下,我希望得到一个错误。目前,我使用
Promise.each
和一个全局
var
实现了这一点,但我认为,有一个更好的解决方案。我将再次考虑使用
Promise.reduce
。事实上,如果我成功读取了一个文件,我认为没有办法阻止
reduce
调用累加器。这里还有两种模式可以做到这一点。请看杰克·阿奇博尔德的评论:你的回答归功于我-谢谢但你是指我上面的评论还是我的另一个答案?@Bergi,另一个答案——我认为是一个评论——一年前。你让我正确地理解了捕获链的简单性,而不是我设计的复杂的承诺反转模式。我找不到它-可能被删除了?一个提出的,似乎是一个可能的候选人:-)@Bergi,这和任何一个都一样好,尽管不是我记得的那个。啊,我明白了。我必须像成功检索文件内容一样处理实际错误。美好的此外,如果上一次读取失败,则文件是只读的。成功读取文件后,剩余路径不会创建承诺。因此,它是一个非常轻量级的在剩余路径上的循环。谢谢
getFirstGoodFileContent([
    './foo/file1.yaml',
    './foo/file2.yaml',
    './foo/file3.yaml'
]).then(function(fileContent) {
    _console.log(fileContent);
}, function(error) {
    // error will be due to :
    // * a non-FILE_NOT_FOUND error having occurred, or
    // * the final path having resulted in an error.
    console.log(error); 
});