You are right. I was mistakenly thinking that the alternative (naive approach) would be to write the promise-creating tasks within the for loop, but if they are not part of the loop, the functionality is basically equivalent to Promise.all.
// A -- Async and parallel
const results = await Promise.all(data.map((i) => delay(i)));
// B -- Functionally equivalent to the above
const promises = data.map((i) => delay(i));
const result = [];
for (let a of promises) {
const r = await a;
result.push(r);
}
// C -- Problematic and naive approach: much slower
const result = [];
for (let i of data) {
const r = await delay(i);
result.push(r);
}