返回一个用备份承诺加强的新承诺

Returning a new promise reinforced with backup promises

我是 promises 的新手,所以我可能遗漏了一些明显的东西。我想要一个以 'promise creators' 列表作为参数和 returns 单个承诺的函数,它要么解决列表中第一个成功的承诺,要么拒绝一些一般性错误。这将用于从网站加载数据,我有几种后备方法以防一种或多种方法失败。

这是我的意思的一个工作示例。有 3 个承诺,m1m2m3,要么成功,要么失败。 tryAll 将尝试每一个,直到其中一个(m3 在这种情况下)解决,它被传递给初始承诺请求的 then 语句。如果要解析 m2 而不是 m3,则永远不会尝试 m3

function m1(){
    return new Promise(function(resolve, reject){
        reject(new Error("Failed 1"));
    });
}

function m2(){
    return new Promise(function(resolve, reject){
        reject(new Error("Failed 2"));
    });
}

function m3(){
    return new Promise(function(resolve, reject){
        resolve("Succeeded 3");
    });
}

function tryAll(methods){
    return new Promise(function(resolve, reject){
        if(methods.length == 0){
            reject(new Error("None worked"));
        }else{
            methods[0]()
                .then(function(data){
                    resolve(data);
                })

                .catch(function(err){
                    methods.shift(); // discard the first since it was already tested
                    tryAll(methods)
                        .then(function(data){
                            resolve(data);
                        })

                        .catch(function(err){
                            reject(err);
                        })
                })
        }
    });
}

tryAll([m1, m2, m3])
    .then(function(data){
        console.log(data);
    })

    .catch(function(err){
        console.log("failed");
    })

有什么方法可以简化 tryAll?或者有什么内置的方法可以让我完成同样的事情吗?

您可以只使用链接而不是 return 新的承诺。例如:

function tryAll(methods) {
  if (methods.length === 0) {
    return Promise.reject('None worked');
  }
  return methods[0]().catch(err => tryAll(methods.slice(1)));
}

tryAll 的 returned promise 可以是方法 [0] 的解析值,或者递归 tryAll 调用的解析值,或者 tryAll 递归最终 运行 的拒绝方法数。

为了迭代地演示这一点,您可以这样做:

function tryAll(methods) {
  return methods.reduce((promise,method) => promise.catch(err => method()), Promise.reject('No methods supplied'));
}

这也会 return 相同的承诺链(尽管在这种情况下,如果 none 失败,它实际上会拒绝最后一个方法错误)