1

I'm trying to use a for loop to cycle through an array of URLs and use them for ajax calls. Outside of the ajax call, i changes value correctly, but when I try and access it from inside the call it always returns 2. It loops correctly but with the same value instead of cycling through 0, 1 etc.

var i = 0;
for(i = 0; i <= 1; ++i) {
    console.log("Value outside of call = " + i);
    $.ajax({
        url : urls[i],
        dataType : 'jsonp',
        timeout : 3000,
        count : 0,
        success : function(data) {
            console.log("Value inside of call = " + i);
            shotInfo[i] = data;
        },
        error : function() {
        }
    })
}

I've tried using a while loop too, but it has the same effect.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
ZeshanA
  • 31
  • 3
  • Typical scoping error. Millions of duplicates. Read a book. – Lightness Races in Orbit Dec 28 '11 at 15:05
  • @TomalakGeret'kal even so, a little harsh. Gave you the +1 before reading this. – Craig Dec 28 '11 at 15:09
  • @Craig: (a) The upvoteability of my answer should have nothing to do with comments elsewhere, so... good. (b) Not harsh at all. This information is freely available everywhere and the question shows zero research effort, which is frowned upon here for obvious reasons. – Lightness Races in Orbit Dec 28 '11 at 15:10
  • 1
    @TomalakGeret'kal whatever lets you sleep well, it's harsh. The guy is probably new. You've never made silly mistakes I guess. Just looked, he is 14 years old. As for the up vote, I agree but I wouldn't bother to give an up vote to someone being rude. – Craig Dec 28 '11 at 15:12
  • 1
    I did research, both SO and the web, sorry. And I'd love to read a book, what would you recommend? – ZeshanA Dec 28 '11 at 15:14
  • 1
    It would be great if we take nothing to our heart and be more professional. This is a beginner question and we must help beginners understand. @ZenshanA You can understand easily from your loggers. You could see the logs inside your AJAX after all your logs outside the AJAX prints. – hop Dec 28 '11 at 15:20
  • @Craig: Then you are not using the system properly. Vote out of facts, not out of some misplaced "kindness". We all learned by failing and, crucially, _being told about it_. – Lightness Races in Orbit Dec 28 '11 at 15:20
  • @TomalakGeret'kal Happy Holidays :) – Craig Dec 28 '11 at 15:22
  • 1
    What would have helped you here is understanding variable scope which is a concept for beginners but I see this confusion come up often enough with ajax and async calls. Remember that your `success` option is a `callback` which is not executed in conjunction with the loop. – Craig Dec 28 '11 at 15:26
  • @Craig Ah, so the `callback` is only executed after `i` has taken it's final value. How would I go about making a closure to fix that? – ZeshanA Dec 28 '11 at 15:39
  • 1
    @hop 's last comment is what you are looking for. You could add the index as a querystring param and return it as a part of the data. – Craig Dec 28 '11 at 15:44

3 Answers3

5

You only have one variable i. When the callbacks fire, it has its final value of 2.

Make a closure.

Community
  • 1
  • 1
Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
2

The call back function is called AFTER the AJAX call completes. To prevent this, try setting async to false

var i = 0;

for(i = 0; i <= 1; ++i) {

console.log("Value outside of call = " + i);

var currentIndex = i;

$.ajax({ url : urls[currentIndex], dataType : 'jsonp', timeout : 3000, count : 0, async : false, success : function(data) {

console.log("Value inside of call = " + currentIndex);

shotInfo[currentIndex] = data;

},

error : function() {

}
    })
}
  • Never set async to false!! Making the user suffer just because it makes your code a bit easier is a bad idea. – Oriol Aug 20 '16 at 22:14
0

Basically, the success call back happens after the AJAX request completes. That may be the issue. Try if this works.

var i = 0;
for(i = 0; i <= 1; ++i) {
    console.log("Value outside of call = " + i);
    var currentIndex = i;
    $.ajax({
        url : urls[currentIndex],
        dataType : 'jsonp',
        timeout : 3000,
        count : 0,
        success : function(data) {
            console.log("Value inside of call = " + currentIndex);
            shotInfo[currentIndex] = data;
        },
        error : function() {
        }
    })
}
hop
  • 2,518
  • 11
  • 40
  • 56
  • Thanks for replying, but that code has the same issue. I'm reading up on closures before I ask any more stupid questions, thanks again! – ZeshanA Dec 28 '11 at 15:29
  • Yes you are correct. Probably, I would suggest you to carry the currentIndex through the AJAX request and read the index from the response. – hop Dec 28 '11 at 15:33
  • I'm sorry for being so thick, but I'm not quite sure what you mean, could you explain what you mean a bit more please, if it isn't too much trouble? – ZeshanA Dec 28 '11 at 17:32
  • You need to send the current index as a parameter in your request and send it back in the response. It can be some thing like url:urls[currentIndex]+'?currentIndex='+currentIndex. And in your code, you need to add it with the response. Say it will be like shotInfo[data.currentIndex] = data.actualData; – hop Dec 29 '11 at 03:58