How to specify the correct value of `i` in a callback in a loop?

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 (this is not mine, so I cannot edit) open a new "thread" of execution.

When I try to print the title at each step, I always get the last possible value of i .

How can I keep a reference to the correct i value for each iteration?

+4
source share
2 answers

You can create a closure inside a 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, we create a function;

 (function (i) { myObject.geocode({ param1: "param" }, function(results, status) { alert(result.title[i]); }); }); 

... which takes one parameter named i and launches a geocode request. Adding (i) to the end of the declaration of the function expression, we immediately start the function 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 the variable i already exists in a higher scope than the closure, because the local declaration i overrides it. Either the variable that we pass to the closure, or the name that the closure calls the variable, can be different;

 (function (anotherVariable) { myObject.geocode({ param1: "param" }, function(results, status) { alert(result.title[anotherVariable]); }); }(aVariable)); 

Alternatively, you can also extract the logic into another function (I prefer it, but it is 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 boils down to the same variable i , which is used by callback functions; which, as you discovered, has moved to the time the callback ended. Both of the above solutions create another variable for each iteration, and that is how the callback works.

+5
source

See closing JavaScript inside loops to see 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); } 
+2
source

Source: https://habr.com/ru/post/1395264/


All Articles