Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Implementing a mix of Promise.all and Promise.settle

I need to implement a version of Promise.all that would take an array of promises and return the result as it usually does, plus also settles all promises, much like Promise.settle does it within the Bluebird library, except I cannot use Bluebird, and have to rely just on the standard promise protocol.

Would that be terribly complicated to implement? Or is it too much to ask here for an idea of how to implement it? I really hope not, so I'm asking, if anyone perhaps implemented it before, to share the idea of how to do it right.

The premise for this is to be able to use it within a database transaction that needs to do commit/rollback once the call has finished, and it cannot have loose promises still trying to resolve outside the transaction call.

EDIT: The link provided to another question is very useful, but it is not a complete answer to the question that was asked. A generic settle is a great example that helped a lot, but it needed to be simplified and wrapped into all logic to fit the transactions scenario described earlier.

like image 273
vitaly-t Avatar asked Sep 08 '15 22:09

vitaly-t


People also ask

Can I use Promise all settled?

The Promise.allSettled() method is one of the promise concurrency methods. Promise.allSettled() is typically used when you have multiple asynchronous tasks that are not dependent on one another to complete successfully, or you'd always like to know the result of each promise.

How do you execute multiple promises?

Approach 1: In this approach, we will use Promise. all() method which takes all promises in a single array as its input. As a result, this method executes all the promises in itself and returns a new single promise in which the values of all the other promises are combined together.

What are the 2 possible outcomes of a Promise?

A promise has 2 possible outcomes: it will either be kept when the time comes, or it won't. This is also the same for promises in JavaScript.

Does Promise allSettled run in parallel?

allSettled(promises) is a helper function that runs promises in parallel and aggregates the settled statuses (either fulfilled or rejected) into a result array.


1 Answers

I think the solution by jfriend is overly complex because it builds on top of settle, it runs a semaphore and does a lot of weird stuff instead of using the built in primitives like .all.

Instead, if we build on Bluebird's newer reflect primitive (implementing it in native promises) we can get a much cleaner API and implementation:

function reflect(promise){
    return promise.then(x => ({state: "fulfilled", value: x}), // arrows, assume nodejs
                        e => ({state: "rejected" , value: e}));
}

On top of reflect, we can build the other primitives easily:

function settle(promises){
    return Promise.all(promises.map(reflect)); // much cleaner
}

If we want to wait and then resolve/reject based on values it's simply:

function allWait(promises){
    return settle(promises).then(results => {
       var firstFailed = results.find(r => r.state === "rejected");
       if(firstFailed) throw firstFailed.value;
       return results; 
    });
}
like image 99
Benjamin Gruenbaum Avatar answered Nov 01 '22 18:11

Benjamin Gruenbaum