Promise.any

Tab Atkins Jr. jackalmage at gmail.com
Thu Jul 17 10:19:56 PDT 2014


On Thu, Jul 17, 2014 at 9:28 AM, Tobie Langel <tobie.langel at gmail.com> wrote:
> Hi all,
>
> [Jake Archibald recently pointed out][1] that the promise returned by
> `Promise.race` is rejected if any of the promises passed to `Promise.race`
> get rejected before one was resolved. So in the following example:
>
> ```
> var p = Promise.race([
>     new Promise(function(_, reject) { reject(new Error("boom!")); }),
>     new Promise(function(resolve) { setTimeout(resolve, 1000, "foo"); })
> ]);
> ```
>
> `p` will be rejected with error `"boom!"` (instead of being resolved with
> value "foo").
>
> Although this seems to fit some use case, it doesn't work when the aim is to
> resolve `p` with whichever promise resolves first and only reject `p` when
> all promises have failed. For example, when doing a cache lookup and racing
> it against the network, you want to display the data from whichever source
> resolves first, and only display a fallback resource when neither the cache
> nor the network are available.
>
> In the same thread, [Tab Atkins mentioned][2] `Promise.any` fulfills this
> use case and was briefly discussed within TC39 before being abandoned.

I think we should, as the use-case seems valuable and is tricky to put
together manually.

I think the errors should be surfaced; we might define a
CompositeError exception class and have it contain an array of the
errors.  (This is necessary to maintain the practical invariant that
UA-rejected promises are alwyas rejected with errors.)

I initially thought that the name might not be too clear, but after
some consideration, I think .any() is fine.  We're trying to
distinguish between "race to settle" and "race to fulfill" here, with
the former already named race().  Luckily, "any" is similar to "all",
both in naming and behavior, as "all" means "all have fulfilled", so
"any" meaning "any have fulfilled" works well.

~TJ


More information about the es-discuss mailing list