Is it legit (or good practice) do a loop with a higher order function - like Array.map()
- to perform some side effects ?
This is mostly a theoretical question since I notice that sometimes I found (or perform myself) some loops using the .map()
method, like this:
let myObject = {...}
let myItemsArray = [ ... , ... ]
myItemsArray.map( (item, index) => {
// do some side effect for ex:
myObject.item[index] = item
}
But I know that this map()
method actually returns an array. So calling myItemsArray.map()
is like I'm returning an array without assign it to any variable.
So the question, is this legit? Should I avoid this and use a classic for()
loop or a .forEach()
method?
Side question: one of the reasons I'm asking this is because I need to perform some loops on an async function so promises and await operators are involved, I remember that forEach()
loops are not ideal on an async function, but wanted to know why.
So the question, is this legit? Should I avoid this and use a classic for() loop or a .forEach() method?
If you aren't returning anything from the map function, then you should use forEach
instead. You end up with the same result but you don't imply, to anyone maintaining your code, that you are returning something useful.
one of the reasons I'm asking this is because I need to perform some loops on an async function so promises and await operators are involved, I remember that forEach() loops are not ideal on an async function, but wanted to know why.
forEach()
is generally not recommended for use with promises because it lacks any feature that can be used to wait for them to resolve. map()
, by itself, has the same problem (but see the final scenario below).
There are three ways I would handle promises in a loop depending on what timing behaviour I wanted from the loop and the code that followed it.
Use a regular for ()
loop so that the function pauses while each promise is awaited.
for (let i = 0; i < array.length; i++) {
await somethingUsing(array[i]);
}
doSomethingWhenAllPromisesAreSettled();
Use a forEach
.
array.forEach((item) => {
somethingUsing(item);
});
doSomethingWhileThePromisesAreInFlight();
Use a map
. Pass the array of returned promises to Promise.all
. Then await
that.
await Promise.all(array.map((item) => {
return somethingUsing(item);
});
doSomethingWhenAllPromisesAreSettled();