兑现承诺后,是否有可能摆脱等待Promise.all(Chrome 80) [英] Is it possible to break away from await Promise.all when any promise has fulfilled (Chrome 80)

查看:62
本文介绍了兑现承诺后,是否有可能摆脱等待Promise.all(Chrome 80)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要向多个服务器发送请求,以查看哪个服务器将响应我的请求,如果其中任何一个响应,那么我将进一步与该服务器进行交互.最简单的方法是按顺序发送我的请求,类似这样

I need to send a request to multi-servers to see which server will response to my request and if any of them response, I will then further interact with this server. The simplest way is to send my request in sequence, something like this

async function probing(servers) {
    for (const server of servers) {
        const result = await fetch(server)
        if (result.status == 200) {
            return result
        }
    }
}

但是我希望加快探测过程,因此我将代码更改为

But I hope to speed up the probing process so I change my code to

async function probing(servers) {
    results = await Promise.all(
        servers.map(async server => {
            return await fetch(server)
        })
    )
    for (const result of results) {
        if (result.status == 200) return result
    }
}

但是我仍然需要等待所有的诺言完成.我真正需要的只是他们中的一个有决心,然后从我的probing()返回

But I still need to await all of promises to finish. What I really need is just if one of them has resolve I then return from my probing()

那是可能吗?

----更新----

---- update ----

感谢评论 promise.any 是解决方案(单线箭头功能可以进一步简化如下)

Thank for the comments promise.any is the solution (and one-liner arrow function can be further simplified as following)

result = await Promise.any(
    servers.map(server => fetch(server))
)

----更新2 ----

---- update 2 ----

我曾经以为 Promise.any 是解决问题的方法.但不幸的是,事实并非如此! Promise.any 仅可用来自Chrome 85+及更高版本FF 79+,与Promise.all不同,它适用于IE以外的任何现代浏览器,请在此处 https://v8.dev/features/promise-combinators

I had thought Promise.any is the way to go and the end of the story. But unfortunately it is not! Promise.any is only available from Chrome 85+ & FF 79+, unlike Promise.all is available for any modern browser except for IE, check here https://v8.dev/features/promise-combinators

我的客户需要我支持2020年以后的Chrome版本,即Chrome 80+,我尝试与Babel填充 Promise.any ,但失败了.

And my client needs me to support Chrome version from 2020, i.e. Chrome 80+, I tried to polyfill Promise.any with Babel but I failed.

我们使用 babel6 ,但我无法用babel6填充Promise.any.我试图升级到 babel7 (带有 npx babel-upgrade --write 和一些变体),现在使用Promise.any()捆绑的代码甚至无法工作chrome88.我问了另一个问题,我如何polyfill Promise.any()使用babel 7?

We use babel6 and I failed to polyfill Promise.any with babel6. I tried to upgraded to babel7 (with npx babel-upgrade --write and some twists) and now the bundled code using Promise.any() can't even work for chrome 88. I asked another question for that How do I polyfill Promise.any() using babel 7?

所以现在我只需要恢复为Promise.all.

So now I just have to revert to Promise.all.

----更新3 ----

---- update 3 ----

我终于在Babel 7上使polyfill Promise.any()起作用了,关键是要在正确的babelrc设置下使用 core-js @ 3 (我不确定我的答案都正确),请参阅我的问题并在此处回答.

I finally made polyfill Promise.any() with Babel 7 work, the key is to using core-js@3 with correct babelrc setting (I am not sure I got them all correct), please refer to my question and answer there.

推荐答案

在这种情况下, Promise.race()看起来很合理,但是 Promise.race()的问题是比赛中任何拒绝的诺言都会使整个比赛崩溃.如果我们想要忽略个别的拒绝并继续进行比赛,那么我们仍然有一个选择,在这种情况下,只有当所有的承诺都被拒绝时,我们才必须执行操作来处理错误.

In this case Promise.race() looks reasonable but the problem with Promise.race() is any rejecting promise in the race will collapse the whole race. If what we want is to ignore the individual rejections and carry on with the race then we still have an option in which case only if all promises gets rejected we have to perform an action to handle the error.

因此,如果我们发明 Promise.invert()并将其与Promise.all()结合使用,我们将得到想要的东西.

So if we invent the Promise.invert() and use it with Promise.all() then we get what we want.

var invert = pr => pr.then(v => Promise.reject(v), x => Promise.resolve(x));

让我们看看如何使用它;

Lets see how we can use it;

var invert     = pr  => pr.then(v => Promise.reject(v), x => Promise.resolve(x)),
    random     = r   => ~~(Math.random()*r),
    rndPromise = msg => random(10) < 3 ? Promise.reject("Problem..!!!")
                                       : new Promise((v,x) => setTimeout(v,random(1000),msg)),
    promises   = Array.from({length: 4}, (_,i) => rndPromise(`Promise # ${i}.. The winner.`));

Promise.all(promises.map(pr => invert(pr)))
       .then(e => console.log(`Error ${e} happened..!!`))
       .catch(v => console.log(`First successfully resolving promise is: ${v}`));

因此,由于现在已经兑现了承诺,所以 catch 是我们处理结果的位置,而 then 是错误处理的位置.

So since the promises are inverted now catch is the place that we handle the result while then is the place for eror handling.

我想您可以在生产代码中安全地使用此代码,只要您为以后阅读的任何人注释该代码块即可.

I think you can safely use this in production code provided you well comment this code block for anybody reading in future.

这篇关于兑现承诺后,是否有可能摆脱等待Promise.all(Chrome 80)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆