【问题标题】:Racing Javascript promises while ensuring all promises complete竞速 Javascript 承诺,同时确保所有承诺都完成
【发布时间】:2022-11-06 08:41:04
【问题描述】:

我需要得到返回的 Javascript Promise 的结果最快的,但我想继续调用封装在其他 2 个“失败”承诺中的逻辑,无论谁获胜。下面的例子。

// The 3 promises I care about
const fetchFromGoogle: Promise<T> = googlePromise()
const fetchFromAmazon: Promise<T> = amazonPromise()
const fetchFromCloudflare: Promise<T> = cloudflarePromise()

// The promise that invoked its logic the fastest
const winner: T = Promise.race([fetchFromGoogle, fetchFromAmazon, fetchFromCloudflare])

在这种情况下,如果 fetchFromAmazon 调用在速度方面获胜,那么我会将结果返回给客户端,但继续异步运行其他两个 Promise。

这是在Cloudflare Worker 中执行的,在继续评估其他函数的同时返回获胜承诺的能力将通过下面链接的waitUntil API 得到支持。

我评估了两个选项:

  1. 一些我不知道的 Javascript API 可以为我做这件事
  2. 使用this 之类的东西来确定哪些承诺丢失并使用Cloudflare Workers context.waitUntil 调用运行它们,这将确保逻辑将继续评估,尽管已将结果返回给客户端。

    据我了解,Promise.All 不会满足此标准,因为在我们等待所有 3 项完成时,我永远不会提前返回获胜的承诺。

【问题讨论】:

  • 看看Promise.race的出处。它非常容易实现,而不是某种只有浏览器才能提供的神奇 API。它只是遍历您的数组并在每个承诺上调用then()。那是你应该开始的地方。
  • @Evert 对我在 (2) 下面提出的解决方案的任何意见。我认为这可能是我眼中最好的,因为这意味着我有点分开Promise.race

标签: javascript typescript async-await promise cloudflare-workers


【解决方案1】:

您可以将.then() 处理程序与Promise.race() 结合使用。 .then() 处理程序允许您单独处理每个结果。 Promise.race() 告诉您第一个完成的时间(以及可选的值是什么):

// The 3 promises I care about
const fetchFromGoogle: Promise<T> = googlePromise().then(result => { 
    /* process this one here whenever it completes */
    return someValue;
});
const fetchFromAmazon: Promise<T> = amazonPromise().then(result => { 
    /* process this one here whenever it completes */
    return someValue;
});
const fetchFromCloudflare: Promise<T> = cloudflarePromise().then(result => { 
    /* process this one here whenever it completes */
    return someValue;
});

// Tells you when the first one is done and what its value was
const winner: T = await Promise.race([fetchFromGoogle, fetchFromAmazon, fetchFromCloudflare]);

请记住,Promise.race() 跟踪第一个解决的承诺(成功或失败) - 它不会给你第一个履行的承诺。所以,如果第一个解决问题的承诺被拒绝,那么这就是Promise.race() 会给你的(被拒绝的承诺)。

您可以改用Promise.any() 来获得第一个履行的承诺。

【讨论】:

  • 谢谢,直到在那之后我才意识到没有赢得的承诺仍然继续执行,这很高兴知道。关于将context.waitUntil 纳入此设计的任何建议?因为这是一个 HTTP 处理程序,所以我需要确保其他两个 Promise 在返回客户端后继续执行。虽然您的解决方案允许操纵响应,但不能保证它们在从处理程序返回后会继续。
  • 顺便说一句,感谢您澄清 raceany。我忘记了那个区别,这会给我带来一些麻烦!
  • @user38643 - 我真的不知道需要context.waitUntil 的环境,但是如果你需要告诉它在所有承诺都解决之前,你可以用context.waitUntil 做一个单独的Promise.allSettled([fetchFromGoogle, fetchFromAmazon, fetchFromCloudflare])
  • 在 JavaScript 中,您可以在多个地方使用相同的 Promise,因此您可以同时使用 waitUntil(Promise.allSettled([a, b])winner = await Promise.race([a, b])
  • @user38643 - 正确。 ab 只是承诺。他们不运行任何东西。它们只是一个通知系统。底层操作运行一次并创建了 Promise。然后,您可以将该承诺用于多种事情。
猜你喜欢
  • 2015-04-24
  • 2016-01-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-01-18
  • 2016-03-27
  • 2021-10-20
  • 1970-01-01
相关资源
最近更新 更多