0

I find it weird that I get this output:

Wait..
Request 2 Complete.
Request 2 Complete.

On a simple for loop:

for (var i = 0, j = urls.length; i < j; i += 1) {
    $.ajax({
        url: urls[i],
        dataType: 'jsonp',
        complete: function() {
            log.append('Request ' + i + ' Complete.' + "\n");
            if (i == (j - 1)) {
                log.append('Done.');
            }
        }
    });

}

How come i is always equal to 2?

Jürgen Paul
  • 14,299
  • 26
  • 93
  • 133
  • 2
    The problem occurs because the closure closes over the *variable* i, not *its value when the closure was created*. Many languages other than JavaScript exhibit this issue, including C# and Visual Basic. Do a search for "access to modified closure" if you want more background on this extremely common error. – Eric Lippert Jan 06 '13 at 14:02

2 Answers2

6

This is, because both calls to i inside your ajax request reference the same i of the for-loop. At the point in time, when the requests are completed (and thus i is accessed) the loop has terminated and i has the final value, here 2.

I think you look for something like this:

for (var i = 0, j = urls.length; i < j; i += 1) {
  !function( i ){
    $.ajax({
        url: urls[i],
        dataType: 'jsonp',
        complete: function() {
            log.append('Request ' + i + ' Complete.' + "\n");
            if (i == (j - 1)) {
                log.append('Done.');
            }
        }
    });
  }( i );
}

By passing the value of i to the immediately executed function, you create a copy of the respective value of i to use inside the ajax-requests.

Sirko
  • 72,589
  • 19
  • 149
  • 183
  • Hi sir, what terminology is this technique called? I'd like to know more about it. Thanks BTW. – Jürgen Paul Jan 06 '13 at 14:18
  • @Hermione In general this is a problem of scope and closure in JavaScript. See, e.g., [this question](http://stackoverflow.com/q/111102/1169798). If there is a specific name for the technique I used, I don't know it, though. – Sirko Jan 06 '13 at 14:22
  • @WearetheWorld No it won't. But each request will have an unique id, which is in the same order as the requests are started. So if you have to do any synchronization of the results, you can use that id. – Sirko May 09 '13 at 06:53
0

try using

     async = false;
in ajax request
sourcecode
  • 1,802
  • 2
  • 15
  • 17
  • That would solve the problem with the value of i but the site would be much slower. Sirkos solution is the better approach. – flec Jan 06 '13 at 13:54