0

Here is the code somebody else posted as a solution:

for (var i = 0; i < array.length; i++) {
(function(i) { // protects i in an immediately called function
  $.getJSON('/api.php?action=query&list=querypage&qppage=' + array[i] + '&format=json', function (data) {
    $('#' + array[i]).text(data.query.querypage.results.length);
  });
})(i);
}

Specifically, what does the (i) do at the end of the function?

oh_snaaap
  • 19
  • 1
  • 4
  • Because it's asynchronous – adeneo Apr 25 '16 at 18:13
  • 1
    [JavaScript closure inside loops – simple practical example](http://stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-practical-example) – adeneo Apr 25 '16 at 18:14
  • 1
    You're passing in the loop index to the IIFE as an argument so it's scoped locally to that function. – Andy Apr 25 '16 at 18:14
  • `$.getJSON` is asynchronous. This means that by the time you receive a response from the server and the callback function is executed, the loop will have ended long ago, and `i` will be `array.length-1` for all your calls. To save it for each call, you can use a JS closure like that. (Another name for this specific implementation: IIFE = Immediately-invoked function expression) – blex Apr 25 '16 at 18:16
  • If you use `let` (ES6) instead of `var` you can do away with the IIFE altogether. – Andy Apr 25 '16 at 18:18

1 Answers1

0

The short answer is, if you don't, the value of i will not be as you expect it to be for later function calls. Removing the closure (the (i)) will make it always the maximum value for all calls, as they all happen instantaneously (such is the nature of asynchronous programming).

You create a function around this call, then call that function with the value of i that you want to preserve the value for when the getJSON finishes. Note also, if you were using ES2015, you could use for(let i = 0; ...) and it would handle the scoping for you.

Seiyria
  • 2,112
  • 3
  • 25
  • 51