当任何承诺已经实现时,是否有可能脱离 await Promise.all (Chrome 80)

Qiu*_*ang 7 javascript google-chrome promise async-await polyfills

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

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

但我希望加快探测过程,所以我将代码更改为

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
    }
}
Run Code Online (Sandbox Code Playgroud)

但我仍然需要等待所有的承诺完成。我真正需要的是,如果其中一个有决心,我就从我的探测中返回()

那有可能吗?

- - 更新 - -

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

result = await Promise.any(
    servers.map(server => fetch(server))
)
Run Code Online (Sandbox Code Playgroud)

---- 更新 2 ----

我原以为Promise.any是要走的路,也是故事的结局。但不幸的是,事实并非如此!Promise.any仅适用于 Chrome 85+ 和 FF 79+,不像 Promise.all 可用于除 IE 之外的任何现代浏览器?在这里查看https://v8.dev/features/promise-combinators

我的客户需要我从 2020 年开始支持 Chrome 版本,即 Chrome 80+,我尝试用 Babel填充 Promise.any但我失败了。

我们使用babel6,但我未能用babel6对 Promise.any 进行 polyfill。我尝试升级到babel7 (有npx babel-upgrade --write一些曲折),现在使用 Promise.any() 的捆绑代码甚至不能用于 chrome 88。我问了另一个问题如何使用 babel 7 填充 Promise.any() ?

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

---- 更新 3 ----

我终于Promise.any()用 Babel 7制作了core-js@3polyfill ,关键是使用正确的 babelrc 设置(我不确定我是否全部正确),请参考我的问题和答案。

Red*_*edu 2

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

因此,如果我们发明Promise.invert()并将其与 Promise.all() 一起使用,那么我们就得到了我们想要的。

var invert = pr => pr.then(v => Promise.reject(v), x => Promise.resolve(x));
Run Code Online (Sandbox Code Playgroud)

让我们看看如何使用它;

var invert = pr => pr.then(v => Promise.reject(v), x => Promise.resolve(x));
Run Code Online (Sandbox Code Playgroud)

因此,由于承诺现在被颠倒了,所以现在catch是我们处理结果的地方,而这then是处理错误的地方。

我认为您可以在生产代码中安全地使用它,只要您很好地注释了此代码块以供将来阅读的任何人使用。

  • 这是 2017 年的一个很好的解决方案,但现在我们有了 [`Promise.any`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/any),您应该就用那个 (4认同)