AFAICT, there are two answers to be given here: the one you're asking for, and the one you need. I'll give both in case someone else stumbles upon this answer from Google.
What you should do
It looks like you're trying to make a bunch of asynchronous calls happen in sequence, and guessing that they'll come back in about three seconds. Of course, if that turns out not to be an accurate guess, you're going to have problems, so what you really want is a function that will be triggered at the instant that the request comes back.
There are two ways to do this - either continuation-passing style (aka callback hell), or with promises. The former is easier conceptually, but gets ugly in a hurry:
$http('url', function (data) {
//this function is called when the AJAX request comes back
//do something with data
$http('url2', function (data) {
//do something with second piece of data after request 2 loads
})
})
This gets to be a real mess when you need an arbitrary number. My preferred solution is a recursive higher-order function, such as the following, although it is possible to do it iteratively:
var launch = function f (i) {
return function (data) {
//do something with data
if (i <= urls.length - 1)
$http(urls[i+1], f(i+1))
}
}
//manually trigger the first one
launch(0)()
The cleaner way is with promises. There are hundreds of tutorials on how to use promises to clean up async code, and here is an example of how to do it for a variable number of requests.
What you asked
If you really want to just launch a bunch of timeouts with different arguments, the trick is to close over each one to cache the value of i
. If you do this:
for (var i = 0; i < 20; i++) {
setTimeout(function () {
//i is 20 by the time this runs...
}, 1000)
}
then all 20 invocations of the function will see i
as 20, which is probably not what you wanted.
The solution is this:
for (var i = 0; i < 20; i++) {
setTimeout((function (j) {
//do something with j, which is a copy of the value of i for this iteration
})(i), 1000)
}
The reason this works is that explicitly-passed primitive function arguments (i.e. numbers) are passed by value, while "passing" a variable by closure (which is what's happening in the broken example) passes by reference, even for primitives.