31

I have a for loop enclosing an ajax call and I'm trying to determine the best method for passing the index from the for loop to the callback function. Here is my code:

var arr = [2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010];

for (var i = 0; i < arr.length; i++)
{
  $.ajaxSetup({ cache:false })
  $.getJSON("NatGeo.jsp", { ZipCode: arr[i], Radius:   
            document.getElementById("radius").value, sensor: false },      
            function(data)
            { 
              DrawZip(data, arr[i]);
        }
  );
}

Currently, only the last value of the arr array is passed due to the asynchronous ajax call. How can I pass each iteration of the arr array to the callback function, aside from running the ajax call synchronously?

ROMANIA_engineer
  • 54,432
  • 29
  • 203
  • 199
user717236
  • 4,959
  • 19
  • 66
  • 102
  • 2
    although this is a duplicate of about [30 other questions](http://stackoverflow.com/questions/tagged/javascript+closures+loops), it is a very common issue when using functions within loops, and I hope you won't mind me modifying one of the tags to push that count up to 31 :) – Anurag May 20 '11 at 20:50

3 Answers3

70

You could use a javascript closure:

for (var i = 0; i < arr.length; i++) {
  (function(i) {
    // do your stuff here
  })(i);
}

Or you could just use $.each:

var arr = [2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010];

$.each(arr, function(index, value) {
  $.ajaxSetup({ cache:false });
  $.getJSON("NatGeo.jsp", { ZipCode: value, Radius:   
    document.getElementById("radius").value, sensor: false },      
    function(data) { 
      DrawZip(data, value);
    }
  );
});
scurker
  • 4,733
  • 1
  • 26
  • 25
  • It's worth nothing that these two solutions are the same, and there is nothing magical about `$.each`. In both cases an anonymous function was used to create a closure. – eradman Apr 08 '15 at 14:22
  • Excellent answer. Thank you. – toni rmc Oct 21 '16 at 19:19
5

I didn't read all 30 questions @Anurag listed, but I found the following callback syntax that seems to work:

(function(year) {
  return (function(data) {DrawZip(data, year);});
})(arr[i])

This replaces the original function(data). Incidentally, the results are in random order, due to the asynchronous response

yitwail
  • 1,999
  • 3
  • 20
  • 27
3

You can even omit for-loop brackets as mentioned by John Resig here i think this way is more readable

for (var i = 0; i < arr.length; i++) (function(i) {

    // async processing
    setTimeout(function(){ 
      console.log(i);
    }, i * 200); 

})(i);
Herbi Shtini
  • 2,002
  • 29
  • 34