Kind of difficult to explain it step by step, but I will try backwards - meaning from your output I will try to mention which line in your code outputed it and when.
// obviously starting inside the callback async runs for each of your 3 items
0 // console.log(item);
counter inner 1 // console.log('counter inner ' + counter);
1 // console.log(item);
counter inner 2 // console.log('counter inner ' + counter);
counter 3 // let's not forget you also call callback() for each item
// which evaluates this condition if (++counter < 3) and starting from here,
// it will be true and will run your else statement
// console.log('counter ' + counter);
2 // console.log(item);
counter inner 3 // console.log('counter inner ' + counter);
counter 4 // console.log('counter ' + counter);
// at this point your promise is already resolved (and yes, only once)
done // prom.then(res => console.log(res))
// Now you are probably questioning where the following output comes from
// remember this condition? if (++counter < 3)
// before starting to evaluate to false and printing to console, once it
// evaluated to true so setTimeout was called with your async callback
// which scheduled it to run on the next "tick"*, which is right after the
// promised was resolved
0
counter inner 4
counter 5
1
counter inner 5
counter 6
2
counter inner 6
counter 7
This is the effect that setTimeout()
with a timeout of 0 does. It is like a thread/process yield in C. Although it seems to say "run this immediately" it actually re-queues the new javaScript code at the end of the execution queue.
According to setTimeout
documentation, its second parameter is the following:
The time, in milliseconds (thousandths of a second), the timer should
wait before the specified function or code is executed. If this
parameter is omitted, a value of 0 is used, meaning execute
"immediately", or more accurately, as soon as possible. Note that in
either case, the actual delay may be longer than intended;
And here you can read more about reasons for delays longer than specified.
You can easily verify what I just explained by changing your if
condition to if(++counter < 2)
. Since it will never evaluate to true, you will see that the console ouput stops at "done"
.