Promise.all to key value results

Advertisements

I was wondering if there is an elegant way to achieve the following:

const res = await Promise.all([taskA, taskB])

Where res will become:

{
taskA: <result of taskA>,
taskB: <result of taskB>
}

(The main reason I’m using Promise.all is because I want to run those tasks in parallel, even though they are distinct in nature).

>Solution :

Totally possible. First, what you need to do is map through all of the tasks you want to do, returning a new array of promises that generate an entry name based on the name of the function and an entry value based on the awaited result:

const taskA = async () => Promise.resolve().then(() => 'foo');
const taskB = async () => Promise.resolve('bar');

(async () => {
    const results = Object.fromEntries(await Promise.all([taskA, taskB].map((func) => (async () => [func.name, await func()])())));

    console.log(results);
})();

Here’s something with a bit more explanation (and easier to read):

const taskA = async () => Promise.resolve().then(() => 'foo');
const taskB = async () => Promise.resolve('bar');

const prettyPromiseAll = async (funcs: Array<(...args: any) => Promise<any>>) => {
    // Since we're generating an array of entries, we can create an object from them
    // once all promises have been awaited.
    return Object.fromEntries(
        // Call Promise.all as normal, making sure to await it.
        await Promise.all(
            // But, for each function...
            funcs.map((func) => {
                // Return an automatically invoked async function (returning a promise)
                // that returns a tuple looking like [nameOfFunction, resultOfPromise]
                return (async () => [func.name, await func()])();
            })
        )
    );
};

(async () => {
    const results = await prettyPromiseAll([taskA, taskB]);

    console.log(results);
})();

Why is this better than the answer below? Because in the answer below, you need to specify the keys for which you’d like the results to have. This method uses the function name.

Note:

This prettyPromiseAll function works differently from regular Promise.all, as it takes an array of functions that return promises, rather than an array of promises.

Leave a ReplyCancel reply