Skip to content

Instantly share code, notes, and snippets.

@sam-w
Created August 5, 2019 03:16
Show Gist options
  • Select an option

  • Save sam-w/247667eac389b446af9e1bc54398e67a to your computer and use it in GitHub Desktop.

Select an option

Save sam-w/247667eac389b446af9e1bc54398e67a to your computer and use it in GitHub Desktop.

Revisions

  1. sam-w renamed this gist Aug 5, 2019. 1 changed file with 0 additions and 0 deletions.
    File renamed without changes.
  2. sam-w created this gist Aug 5, 2019.
    32 changes: 32 additions & 0 deletions Promise.firstSuccess
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,32 @@
    /**
    * Executes a list of Promises in parallel and resolves with the first successful resolution.
    *
    * Like `Promise.race` in that it takes a list of Promises and only waits for the first completion, but
    * differs in that it requires a _successful_ resolution before it completes. Only rejects if _all_ children reject.
    *
    * Different
    * @param promises a list of promises to resolve.
    * @param where an optional predicate. Any Promise `p` which resolves but for which the predicate
    * produces an error will behave as `p` instead rejected.
    */
    // Do not let tslint convert this to async. It will get it wrong and change the behaviour.
    // tslint:disable-next-line: array-type
    function firstSuccess<T>(promises: Promise<T>[], predicate?: (value: T) => Error | null): Promise<T> {
    return Promise.all(promises.map((p) => {
    // If a request fails, count that as a resolution so it will keep
    // waiting for other possible successes. If a request succeeds,
    // treat it as a rejection so Promise.all immediately bails out.
    return p.then(
    (val) => {
    const e = predicate && predicate(val);
    return e ? Promise.resolve(e) : Promise.reject(val);
    },
    (err) => Promise.resolve(err),
    );
    })).then(
    // If '.all' resolved, we've just got an array of errors.
    (errors) => Promise.reject(errors),
    // If '.all' rejected, we've got the result we wanted.
    (val) => Promise.resolve(val),
    );
    }