1

I'm working on this code puzzle from here

Here's what I have so far:

for (var i = 0; i < 1000; i += 100) {
    waitFor(i, function then() {
    console.log(i)
    })
}

// this will run a callback function after waiting milliseconds
function waitFor(milliseconds, callback) {
    setTimeout(callback.apply(), milliseconds)
}

This logs out 0 to 900, but it does it all at once, and then waits 900 milliseconds at the end (instead of waiting i milliseconds in between each console.log).

Can anyone help me understand this?

Ber
  • 695
  • 1
  • 11
  • 17

2 Answers2

0

You have two different issues going on in your code:

  1. Closures are causing the value 1000 to printed always instead of 100, 200 ... etc.
  2. The timeouts you are using are too short, so the functions are executing rapidly in succession.

The first problem is hard to explain in a single answer but I will try to give you some insights, since the function that is printing the value of the variables to the console is defined inside the for loop, that function will always keep the value of i that was there when the loop ended, and in your situation this is 1000.

To solve this problem, you need something similar to what @thg435 referred to in his comment, something like this:

// this will run a callback function after waiting milliseconds
function waitFor(milliseconds, callback) {
    setTimeout(callback, milliseconds);
}

function createFunction(i) {
    return function() { console.log(i); };
}

for (var i = 0; i < 1000; i += 100) {
    waitFor(i, createFunction(i));
}

The second problem is that the values for the timeout are actually the values that i take as it is looping which are 100, 200 ... etc which are all very small values less than a second, so when the for loop finishes, those functions will all be ready to executed so they will get executed immediately one after the other.

To solve this issue you need to use a bigger time gap by multiplying i by 10 for example, like the following:

waitFor(i*10, createFunction(i));
        ^^^^
Ibrahim Najjar
  • 19,178
  • 4
  • 69
  • 95
  • I tried that and it just logged out "1000" 10 times immediately. – Ber Nov 26 '13 at 10:20
  • @Ber I have completely modified my answer to a new one, please check the edit. I was very busy when I answered the first time and I messed everything up, sorry for that. – Ibrahim Najjar Nov 26 '13 at 14:31
  • Thanks Sniffer for the explanation, I modified the code along those lines and it works now! – Ber Nov 26 '13 at 22:34
  • @Ber You are welcome, glad I could help. You need to read deeply about closures because they are a nasty subject, but once you understand them very well you will find them very useful. – Ibrahim Najjar Nov 27 '13 at 06:34
0

First timer call will be happenned when loop will be finished. In this context i = 1000 due to JS uses reference not a value. To fix this situation you have to use closures.

maximus
  • 716
  • 7
  • 18