Reputation: 47995
I have this code :
for (var i = 0; i < result.length; i++) {
// call a function that open a new "thread"
myObject.geocode({ param1: "param" }, function(results, status) {
alert(result.title[i]);
});
}
The .geocode
function (that is not mine, so I can't edit) open a new "thread" of execution.
When I try to print title on each step, I get always the last possible value of i
.
How can I keep a reference to the right value of i
for each iteration?
Upvotes: 4
Views: 120
Reputation: 75327
You can create a closure within the loop;
for (var i = 0; i < result.length; i++) {
// call a function that open a new "thread"
(function (i) {
myObject.geocode({ param1: "param" }, function(results, status) {
alert(result.title[i]);
});
}(i));
}
So here we're creating a function;
(function (i) {
myObject.geocode({ param1: "param" }, function(results, status) {
alert(result.title[i]);
});
});
... which accepts one parameter named i
, and launches the geocode request. By adding the (i)
to the end of the declaration of a function expression, we run the function straight away and pass it the current value of i
.
(function (i) {
myObject.geocode({ param1: "param" }, function(results, status) {
alert(result.title[i]);
});
}(i));
It doesn't matter that a variable i
already exists at a higher scope than the closure, because the local declaration of i
overrides it. Either the variable we pass to the closure, or the name the closure calls the variable could be different;
(function (anotherVariable) {
myObject.geocode({ param1: "param" }, function(results, status) {
alert(result.title[anotherVariable]);
});
}(aVariable));
Alternately you could also extract the logic to another function (I prefer it, but it's less cool):
function geocode(i) {
myObject.geocode({ param1: "param" }, function(results, status) {
alert(result.title[i]);
});
}
for (var i = 0; i < result.length; i++) {
geocode(i);
}
The problem is down to the same i
variable being used by the callback functions; which, as you've discovered, has moved on by the time the callback executes. Both of the above solutions creates another variable for each iteration, and it is this that the callback operates on.
Upvotes: 5
Reputation: 143204
See JavaScript closure inside loops to understand why your code doesn't work.
for (var i = 0; i < result.length; i++) {
var callback = (function(i) {
return function(results, status) {
alert(result.title[i]);
};
})(i);
myObject.geocode({ param1: "param" }, callback);
}
Upvotes: 2