1

I need to get the right i values for each and every one of my response values (JSON loads). How do I do that?

Lets say I have 10 JSON files. All of them must be loaded, stored and displayed to the client in the proper order.

So it should look something like this:

for (var i = 0; i < files.length; i++) {
    $.getJSON(files[i], function (response) {
        console.log(i);
        console.log(response);
    });
}

The result of the response is what we would expect - the contents of the file, but the variable i always seems to be the same (= files.length). My explanation for this would be that JS is not a language that waits for a specific action to complete, it can do a lot of actions in the same time (forgot the scientific name for this).

ATOzTOA
  • 34,814
  • 22
  • 96
  • 117
  • you mean it's "asynchronous". basically your code is firing off `files.length` worth of nearly simultaneous requests at the server, not waiting for the previous one(s) to finish. when the `function(response)` does kick in, `i`i is almost guaranteed to be some **OTHER** value than the current response was sent out with. – Marc B Feb 16 '13 at 04:26
  • 2
    http://stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-practical-example –  Feb 16 '13 at 04:32

1 Answers1

4

The problem stems from the fact that your callback isn't closing over the value of i in effect when it's registered; every callback sees the same instance of i, which ends up having the value it has after the loop completes (which is files.length).

The sensible thing to do, with jQuery, is to use $.each as coder says. But the way to solve it with pure javascript would be:

for (var i = 0; i < files.length; i++) {
    (function(idx) {
        $.getJSON(files[idx], function (response) {
            console.log(idx);
            console.log(response);
        });
    })(i);
}

By making, and then immediately calling, the anonymous function, you rebind the value in i to a new local variable named idx scoped to that function. Each callback then carries around its own idx, so it will end up logging the correct value (what i was when you registered the callback, instead of what it became later). This is actually exactly what's happening when you use $.each, since each has you pass in an anonymous function that receives the index as a parameter.

hobbs
  • 223,387
  • 19
  • 210
  • 288