I would really like to see a tutorial on how to solve this the right way -- right now it seems that everybody does it the "wrong way" and the problem isn't even mentioned.
Common pattern #1 (tuple-style):
const result = await Promise.all([
someAsyncFunction1(computeArg1()),
someAsyncFunction2(computeArg2()),
]);
Common pattern #2 (array-map-style): const result = await Promise.all(elements.map(x => someAsyncFunction3(computeArg3(x))));
Both suffer from the same problem: If computeArg2 / computeArg3 potentially throw a (synchronous) error, then some promises have already been created, but Promise.all() never runs and so they don't have a catch-handler. If one of those rejects ("throws asynchronously") then that rejection is unhandled and crashes the process.The problem is also discussed here, but in the context of "should ECMAScript be changed": https://es.discourse.group/t/synchronous-exceptions-thrown-f...
const result = await Promise.allSettled(elements.map(async x => someAsyncFunction3(computeArg3(x))));For the second example, it's kind of a weird one, but I'm actually a fan of using async .reduce to accomplish that. It took me a minute the first time I saw someone do it, but I think it more cleanly solves the problem and gives you more control over the result.
In this particular case it's a lot more verbose, obviously, but if you're doing any kind of further processing of each element, you can move it into the reduce and be able to control exactly what you get out of it if something fails for any reason, while still running mostly concurrently like all or allSettled would.
const result = await elements.reduce(async (collector, x) => {
const arg3 = computeArg3(x) // explicitly handle whatever errors, try catch, whatever you need
const asyncResult = await someAsyncFunction3(arg3)
// this has to happen after calling someAsyncFunction because it will block until the previous iteration finishes
collector = await collector;
collector.push(result)
return collector
}, []);Then what is the issue described in #1?
Ahh, the compute arg calls