Reputation: 75
I run this code on Nodejs and I expect that got an error but it worked!
If I set 2500 ms to setTimeout
I got an error and it’s normal.
Is there anybody here to explain it for me?
And why I see IIFE
log first?
I run this code on browser and got error as I expected.
const data = [{}]
const myPromise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve([1,2,3,4]);
}, 3000);
});
console.log('hiiii');
setTimeout(() => {
data[0].map(e => console.log('to ',e))
}, 2999);
(async() => {
data[0] = await myPromise
data[0].map(e => console.log('iife ',e))
}
)()
console.log('byeeeee')
The below code is what I see on my console
hiiii
byeeeee
iife 1
iife 2
iife 3
iife 4
to 1
to 2
to 3
to 4
Upvotes: 3
Views: 1299
Reputation: 545
The questions related to asynchronous JavaScript can be answered by investigating the event loop only.
How asynchronous JavaScript works?
Let's take an example:
setTimeout(function timeout()
{
console.log('Set timeout finished!');
}, 0);
Promise.resolve(1).then(function resolve()
{
console.log('Resolved!');
});
The immediately resolved promise is processed before an immediate timeout. Because of the event loop priorities dequeuing jobs from the job queue (which stores the fulfilled promises' callbacks) over the tasks from the task queue (which stores timed out setTimeout() callbacks).
Upvotes: 1
Reputation: 541
If line 10 happens to execute at least 1 ms after line 2, then its callback will get queued to run after the callback with the resolve() (and hence after the "iife" logging, which happens in the aftermath of the resolve()).
The solution is to move the second setTimeout() before the first one, to ensure their callbacks are queued in the expected order. So, for instance, this code:
const data = [[99]];
setTimeout(() => {
data[0].forEach(e => console.log('to ',e))
}, 2999);
const myPromise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve([1,2,3,4]);
}, 3000);
});
console.log('hiiii');
(async() => {
data[0] = await myPromise
data[0].forEach(e => console.log('iife ',e))
}
)();
console.log('byeeeee');
reliably produces this result:
hiiii
byeeeee
to 99
iife 1
iife 2
iife 3
iife 4
The logic of the event loop is such that calling setTimeout will queue its callback to become runnable x milliseconds after the current time. Once that amount of time passes, it then has to wait for whatever task is currently executing to finish, and then wait for any other tasks that got queued ahead of it, before it can actually run.
Not sure what you're trying to do, but you'll never get the "to 1" line to appear before the "iife 4" line, because everything from setting data[0] to logging "iife 4" happens inside a single, synchronous chunk of code.
Upvotes: 3