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).
CodePudding user response:
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.
CodePudding user response:
Here is an option if taskA and taskB can be hardcoded and you are ok with shadowing variables.
const res = await Promise.all([taskA, taskB]).then(([taskA, taskB]) => ({taskA, taskB}));
But it would be pretty similar to:
const [tA, tB] = await Promise.all([taskA, taskB]);
const res = {taskA: tA, taskB: tB};