Reputation: 1851
I currently have a for loop like this:
async myFunc() {
for (l of myList) {
let res1 = await func1(l)
if (res1 == undefined) continue
let res2 = await func2(res1)
if (res2 == undefined) continue
if (res2 > 5) {
... and so on
}
}
}
The thing is that func1, func2 are network calls which return promises, and I don't want them to block my for loop while waiting for them. So I don't mind working in parallel with myList[0] and myList[1], nor do I care about the order in which the items of the list are processed.
How can I achieve this?
Upvotes: 2
Views: 3383
Reputation: 1074545
I'd do it by writing a function that handles the one value that you're handling sequentially:
async function doOne(l) {
let res1 = await func1(l);
if (res1 == undefined) {
return /*appropriate value*/;
}
let res2 = await func2(res1);
if (res2 == undefined) {
return /*appropriate value*/;
}
if (res2 > 5) {
// ... and so on
}
}
Then I'd use Promise.all
with map
to start all of those and let them run in parallel, getting the results as an array (if you need the results):
function myFunc() {
return Promise.all(myList.map(doOne)); // Assumes `doOne` is written expecting to be called via `map` (e.g., won't try to use the other arguments `map` gives it)
// return Promise.all(myList.map(l => doOne(l))); // If we shouldn't make that assumption
}
If myList
is (or may be) a non-array iterable, use Array.from
to get an array to use map
on:
function myFunc() {
return Promise.all(Array.from(myList.map(doOne)));
}
(Or use a for-of
loop pushing to an array.)
If you don't want a failure to handle one entry in the list to prevent seeing the results from handling others in the list, use Promise.allSettled
rather than Promise.all
. (Note that they'll all be started either way, the only difference is whether you see the successful results when at least one of them fails.)
Upvotes: 5