Асинхронный forEach
Первоначально давайте взглянем на polyfill метода. На сайте developer.mozilla.org реализация достаточно подробно описывает всю суть данного метода. Если опустить все проверки на существование тех или иных объектов в контексте текущего браузера и стандарта, то можно написать примерно такой метод, выделив основные действия:
Array.prototype.forEach = function (callback) {
for (var i = 0; i < this.length; i++)
callback(this[i], i, this);
};
В данном примере отсутствует проверка на контекст. В качестве аргумента у нас выступает только callback.
Далее мы инициализируем массив и напишем метод, который будет симулировать fetch запрос. Для простоты я решил создать массив чисел. Функция «stubFetch» принимает два аргумента: первый — элемент массива, второй — время в миллисекундах. Promise возвращает setTimeout, который просто выводит значения в консоль.
let stubArr = [1, 2, 3]
function stubFetch(value, time) {
return new Promise(resolve => {
setTimeout(() => {
console.log(value)
resolve(true)
}, time)
})
}
Попробуем применить нативный метод.
stubArr.forEach(async (item, index) => {
console.log('foo')
await stubFetch(value, index * 1000)
console.log('bar')
})

В консоли мы увидим вывод фразы «foo» на каждой итерации, а «bar» в контексте данного решения не имеет смысла. А что, если мы хотим просмотреть ответ сервера и провести какие-то DOM-манипуляции? Или запушить его в массив ответов например? В данном случае достаточно сделать callback асинхронным.
async function asyncForEach(arr, callback) {
for(let i = 0; i < arr.length; i++)
await callback(arr[i], i, arr)
}
// 1ый вариант использования
asyncForEach(stubArr, async (value, index) => {
await stubFetch(value, index * 1000)
}).then(_ => console.log('Finish'))
// 2й вариант использования
async function index() {
await asyncForEach(stubArr, async (value, index) => {
await stubFetch(value, index * 1000)
})
console.log('Finish')
}
index()
// 3ий вариант использования
Promise.all([asyncForEach(stubArr, async (value, index) => {
await stubFetch(value, index * 1000)
})]).then(_ => console.log('Finish'))

Все три варианта использования асинхронного forEach делают абсолютно одно и тоже. Все зависит от стандартов компании, от личных предпочтений, ну и конечно же от поддержки async/await. Конечно же, данным постом я не открыл Америку, но для возможных дискуссий будет в самый раз.