Javascript 先兑现诺言

Javascript 先兑现诺言,javascript,node.js,promise,es6-promise,Javascript,Node.js,Promise,Es6 Promise,如果我有两个承诺A和B,其中只有一个会成功,我怎么能得到其中一个成功实现?我正在寻找类似于Promise.race的东西,但它只会返回第一个实现的承诺。我使用的是ES6中的承诺。如果您希望第一个承诺能够成功解决,并且希望忽略在此之前出现的任何拒绝,那么您可以使用类似以下内容: // returns the result from the first promise that resolves // or rejects if all the promises reject - then retu

如果我有两个承诺A和B,其中只有一个会成功,我怎么能得到其中一个成功实现?我正在寻找类似于
Promise.race
的东西,但它只会返回第一个实现的承诺。我使用的是ES6中的承诺。

如果您希望第一个承诺能够成功解决,并且希望忽略在此之前出现的任何拒绝,那么您可以使用类似以下内容:

// returns the result from the first promise that resolves
// or rejects if all the promises reject - then return array of rejected errors
function firstPromiseResolve(array) {
    return new Promise(function(resolve, reject) {
        if (!array || !array.length) {
            return reject(new Error("array passed to firstPromiseResolve() cannot be empty"));
        }
        var errors = new Array(array.length);
        var errorCntr = 0;
        array.forEach(function (p, index) {
            // when a promise resolves
            Promise.resolve(p).then(function(val) {
                // only first one to call resolve will actually do anything
                resolve(val);
            }, function(err) {
                errors[index] = err;
                ++errorCntr;
                // if all promises have rejected, then reject
                if (errorCntr === array.length) {
                    reject(errors);
                }
            });
        });
    });
}
我不知道如何使用
Promise.race()
,因为它只报告要完成的第一个承诺,如果第一个承诺被拒绝,它将报告拒绝。所以,它并不是按照你在问题中提出的要求去做,即报告解决的第一个承诺(即使一些拒绝在它之前完成)


仅供参考,它既有
Promise.some()
又有
Promise.any()
,可以为您处理这种情况。

反转承诺的极性,然后您可以使用
Promise.all
,因为它拒绝了第一个被拒绝的承诺,在反转后对应于第一个履行的承诺:

const invert=p=>newpromise((res,rej)=>p.then(rej,res));
const firstOf=ps=>invert(Promise.all(ps.map(invert));
//仅在测试中使用的实用程序例程。
const wait=ms=>newpromise(res=>setTimeout(()=>res(ms),ms));
const fail=f=>Promise.reject(f);
const log=p=>p.then(v=>console.log(“通过”,v),v=>console.log(“失败”,v));
//测试。
日志(第一个([等待(1000),等待(500)]);
日志(第一个([等待(1000),失败(“f1”)));

日志(第一个([失败(“f1”)、失败(“f2”))我问了同样的问题,试了一下。通过自己尝试这些问题,你学到了很多

  • 公认的答案非常优雅,但使用了
    承诺。所有的
    都为学习承诺的人带来了乐趣;也有点难以理解
  • jfriend00
    的答案与我的答案相似,但其逻辑超出了承诺的基本原则,而这在这里是最重要的 我已经使用了公认答案中的这些很好的帮助函数:

    功能第一承诺(承诺人、承诺人){
    返回新承诺((解决、拒绝)=>{
    然后(l=>{
    决议(l);
    }).catch(错误=>null);
    promiseR.then(r=>{
    决议(r);
    }).catch(错误=>null);
    承诺捕获(错误=>{
    promiseR.catch(error=>{
    拒绝(errorL+ERROR);
    })
    })
    })
    }
    const wait=ms=>newpromise(res=>setTimeout(()=>res(ms),ms));
    const log=p=>p.then(v=>console.log(“通过”,v),v=>console.log(“失败”,v));
    日志(firstPromise(等待(1000),等待(500));
    日志(firstPromise(等待(1000),Promise.reject(“Bar”));
    日志(firstPromise(Promise.reject(“Foo”),wait(500));
    日志(第一承诺(承诺。拒绝(“Foo”)、承诺。拒绝(“Bar”))ES2021/ES12-Promise.any
    
    承诺。任何
    -首先履行的承诺获胜

    const promiseA = Promise.reject();
    const promiseB = new Promise((resolve) => setTimeout(resolve, 100, 'succeed'));
    
    const promises = [promiseA, promiseB];
    
    
    Promise.race(promises).then((value) => console.log(value)); // rejected promise
    
    Promise.any(promises).then((value) => console.log(value)); // "succeed"
    
    请注意,
    any
    忽略了第一个被拒绝的承诺-
    promiseA
    ,因为
    promiseB
    正在被解析

    如果所有给定的承诺都被拒绝,那么返回的承诺将被拒绝



    这是并且计划在ES2021(预计于2021年6月发布)

    您应该使用
    p.then(…,…)
    而不是
    p.then(…);p、 捕获(…)
    以避免未处理rejections@Bergi-哪里有未经处理的拒绝?如果
    p
    拒绝,则
    p的结果。然后(…)
    是一个被拒绝且从未处理过的承诺。我说的是结果。在
    q=p.then(…);p、 catch(…)
    p
    的拒绝被处理(两次),是的,但对
    q
    的拒绝从未被处理,因此被全局报告,这是错误的。ES7指定了未经处理的拒绝如何工作,并且它们确实错误地使用了您的原始代码。你的书关于
    。然后(…)。catch(…)
    是正确的,但它说的是一般性的,这是我们想要
    。然后(…,…)
    (我们永远不希望
    fn1
    fn2
    两者都被称为)的一种特殊情况,这并不是完全错误的,因为你的
    fn1
    从不抛出,但它更干净,效率更高,如果您在
    fn1
    中犯了错误(如打字错误),将正确报告。您正在寻找
    承诺。任何
    (,…)聪明。这不是第一次在promise land中使用倒置的概念。@jfriend00对,这种技术至少在另一个答案中显示出来了,所以我无法找到,不是原创的。这是一个聪明的破解方法。@torazaburo,你可能看到过,它也可以写成
    promise.prototype.invert()
    promise.any()
    -这将返回解决或拒绝的承诺,而不是第一个实现的承诺。西里尔文的注释是怎么回事?
    const promiseA = Promise.reject();
    const promiseB = new Promise((resolve) => setTimeout(resolve, 100, 'succeed'));
    
    const promises = [promiseA, promiseB];
    
    
    Promise.race(promises).then((value) => console.log(value)); // rejected promise
    
    Promise.any(promises).then((value) => console.log(value)); // "succeed"