Can someone explain me that:
const array = [0, 1, 2, 4, 8, 16, 32, 16, 8, 4, 2, 1, 0];
for (let i = 0; i < array.length; i++) {
setTimeout(function () {
console.log(array[i]);
}, array[i])
}
Can someone explain me that:
const array = [0, 1, 2, 4, 8, 16, 32, 16, 8, 4, 2, 1, 0];
for (let i = 0; i < array.length; i++) {
setTimeout(function () {
console.log(array[i]);
}, array[i])
}
Why this return 0 1 1 0 2 2 4 4 8 8 16 16 32, instead of array items one by one?
Share Improve this question edited Oct 6, 2018 at 18:07 M.A.K. Ripon 2,1483 gold badges30 silver badges48 bronze badges asked Oct 6, 2018 at 14:05 Mateusz DanilukMateusz Daniluk 1252 silver badges9 bronze badges 11- 3 Possible duplicate of setTimeout in for-loop does not print consecutive values – Dexygen Commented Oct 6, 2018 at 14:08
-
1
@GeorgeJempty Not a duplicate. OP uses
let
. – Ivar Commented Oct 6, 2018 at 14:10 -
2
The delays are all different based on value of
array[i]
. What exactly are you wanting to acplish? – charlietfl Commented Oct 6, 2018 at 14:13 -
1
It makes a difference that
let
binds to a separate value when it is inside a closure. Usingvar
would causeundefined
to be printed because at the time it logs, it thei
will be equal to the array lenght. (And since, arrays are zero-based, will try to fetch an element that is not there.) – Ivar Commented Oct 6, 2018 at 14:21 - 4 The problem here is just that the timeout length is the value of the element, so of course the higher values are logged later, because the timeout is longer. – Ivar Commented Oct 6, 2018 at 14:22
4 Answers
Reset to default 5The numbers are appearing one after another. However you won't be able to see that because you have set a very low delay between them. Some of them will appear together. Those are the ones having the same value for array[i]
.
For better seeing the delay between them, I would suggest replacing array[i]
by array [i] * x
, where x
is a number. Look at this:
const array = [0, 1, 2, 4, 8, 16, 32, 16, 8, 4, 2, 1, 0];
for (let i = 0; i < array.length; i++) {
setTimeout(function () {
console.log(array[i]);
}, array[i] * 500)
}
0 will be echoed after 0 × 0.5 = 0 seconds.
1 will be echoed after 1 × 0.5 = 0.5 seconds.
2 will be echoed after 2 × 0.5 = 1 seconds.
4 will be echoed after 4 × 0.5 = 2 seconds, and so on.
EDIT: If you are asking about the reason why 0 1 1 0
is logged instead of 0 0 1 1
, it is likely because the puter takes some small time looping through the array, and before it reaches the final "0", 1 millisecond would have passed, so it will be time to log "1" and "1". Notice that increasing the delay between the logs solves the problem.
When setTimeout()-ing, 0 and 1 mean practically the same thing for a browser (that's why your zeros and ones are mixed at the beginning). All the other numbers are correctly showing up with the delay you're giving them, so first the smallest (and they get scheduled first), then the 2, 4, etc, these will appear later (only a very little bit later) on the console. If you slow this thing down, as @WaisKamal suggested, this timed order will be obvious. So by the time your second zero appears, all the other outputs are already scheduled (that is, setTimeouts themselves all happened, in the order of the array), and then they run in the order of timing.
Your code should log array elements in increasing order:
0,0,1,1,2,2,3,3,4,4,16,16,32.
And it would if you changed timeout to larger values:
const array = [0, 100, 200, 400, 800, 1600, 3200, 1600, 800, 400, 200, 100, 0];
for (let i = 0; i < array.length; i++) {
setTimeout(function () {
console.log(array[i]);
}, array[i])
}
The reason why your code doesn't work as expected is order in which setTimeout callbacks are executed.
You can think of it this way - after timeout defined in setTimeout has passed the callback is added to the some kind of queue, that runs it as quickly as possible(remember that js is single threaded). In your case callback for last element of array is added to that queue after callback for first, second and third element(because your loop execution takes more than 1 millisecond).
It is because the execution of the loop , is faster than your setTimeout
function delay, so that's why the number with minimum delay executes first.