According to JavaScript, Node.js: is Array.forEach asynchronous?, Array.forEach is synchronous. However, for my code below:
function wait5() {
return new Promise(resolve =>
setTimeout(resolve, 5000));
}
async function main() {
console.log("Start");
[1,2].forEach(async (e) => {
const d = await wait5().then(()=> console.log("5s later") )
})
console.log("This should e last!");
}
main();
The output is:
Start
This should e last!
5s later
5s later
with the two "5s later" ing out in rapid succession.
Why is this the case?
If I use a normal for
loop:
async function main() {
console.log("Start");
for (let i=0;i<2;i++) {
const d = await wait5().then(()=> console.log("5s later") )
}
console.log("This should e last!");
}
then the result is what I wanted:
Start
5s later
5s later
This should e last!
According to JavaScript, Node.js: is Array.forEach asynchronous?, Array.forEach is synchronous. However, for my code below:
function wait5() {
return new Promise(resolve =>
setTimeout(resolve, 5000));
}
async function main() {
console.log("Start");
[1,2].forEach(async (e) => {
const d = await wait5().then(()=> console.log("5s later") )
})
console.log("This should e last!");
}
main();
The output is:
Start
This should e last!
5s later
5s later
with the two "5s later" ing out in rapid succession.
Why is this the case?
If I use a normal for
loop:
async function main() {
console.log("Start");
for (let i=0;i<2;i++) {
const d = await wait5().then(()=> console.log("5s later") )
}
console.log("This should e last!");
}
then the result is what I wanted:
Start
5s later
5s later
This should e last!
Share
Improve this question
edited Aug 30, 2018 at 17:12
u936293
asked Aug 30, 2018 at 16:59
u936293u936293
16.3k34 gold badges121 silver badges219 bronze badges
6
-
8
The
.forEach()
mechanism on its own performs no asynchronous work. The same cannot be said for code that's passed in as the callback, which is free to do anything it wants. – Pointy Commented Aug 30, 2018 at 17:01 -
1
await
is the key here. – zero298 Commented Aug 30, 2018 at 17:02 -
1
This has nothing to do with
forEach
and everything to do with[1,2].forEach(async (e) =>
where you declared the callback toforEach
to beasync
. – gforce301 Commented Aug 30, 2018 at 17:02 -
And note that nothing pays attention to the Promise returned from each call to the
.forEach()
callback. – Pointy Commented Aug 30, 2018 at 17:02 - This is your second question about asynchronicity in JavaScript. I'm all for that, please keep asking well formed questions. However, is there a core question that might be better asked like "What does asynchronicity actually mean in JS?" or "How does the event loop work?"? I'm not sure how better to help you. – zero298 Commented Aug 30, 2018 at 17:05
2 Answers
Reset to default 10forEach
is synchronous. Your particular callback function, however, is not. So forEach
synchronously calls your function, which starts its work, once for each entry in the array. Later, the work that started finishes asynchronously, long after forEach
has returned.
The issue is that your callback is async
, not that forEach
is asynchronous.
In general, when you're using an API like forEach
that doesn't do anything with the return value (or doesn't expect a promise as a return value), either:
Don't pass it an
async
function, orEnsure that you handle errors within the function itself
Otherwise, you'll get unhandled errors if something goes wrong in the function.
Or of course:
- Use a
try
/catch
block within theasync
function to catch and handle/report errors within the function itself.
It looks like you're declaring an async
function inside of a caller that really doesn't care for that sort of thing, forEach
. Declaring a function async
makes it promise-like, but that promise is only useful if acted on.
If you need a promise-aware forEach
, that's something you could implement, though Promise.each
in libraries like Bluebird already do that.