Async-await и foreach() в узле

Несколько дней назад, когда я писал небольшой скрипт узла, я пытался загрузить изображения в итерации по массиву, поэтому я подумал об использовании foreach для итерации массива. При этом абстрактный код, который я написал, был следующим:

int i = 0;
foreach(array, async (url) => {
 await download(url);
 i = i + 1;
 console.log(i, "image downloaded");
})

Во время выполнения я столкнулся с необычным поведением foreach(). Результатом кода было то, что значение i было напечатано без ожидания загрузки изображения. Я поискал об этом в Google и нашел альтернативу для... для которой async-await работал нормально.

Я начал копаться в функции foreach и прочитал, что foreach выполняется в стеке, а не в цикле событий, из-за чего асинхронная функция загрузки переходит в цикл событий, который возвращается после выполнения функции foreach в стеке. Когда стек очищается, функция из цикла событий возвращается в стек. альтернатива для… кода будет следующей:

async for(url of array) {
 await download(url);
}

Чтобы узнать больше об этом, прочитайте полифилл foreach и map.