First, I'm grabbing some zip codes from a json file. After that is done loading, I loop through the zip codes and connect to
http://api.geonames.org/postalCodeSearchJSON?postalcode="+zip+"&maxRows=1&username=demo
and replace "zip" with the zip code foreach zip code. So if I have 30 zip codes, it calls this URL 30 times and grabs the Latitude and Longitude for each zip code and places them in an array.
The problem is, I'm trying to use my array before it's being fully built by the ajax call. A work around I'm doing is doing a setTimeout() for 3 seconds so the browser has time to fully build the array and then I can use it.
I'm currently using
$.getJSON( "zip-codes.json", function(){}).done(function(locations){
// this .done() isnt actually working
});
Below is all my code:
var marker_object = new Array;
// get location zip codes
$.getJSON( "zip-codes.json", function(){}).done(function(locations){
// for each zip code
$(locations.nodes).each(function(i, location_value){
var name = location_value.node.city+', '+location_value.node.state+'
'+location_value.node.phone;
var zip = location_value.node.zip;
// if zip is not empty
if(zip != ''){
// get lat, long for each zip
$.getJSON( "http://api.geonames.org/postalCodeSearchJSON?postalcode="+zip+"&maxRows=1&username=midnetmedia", function(){}).done(function(long_lat){
// loop thru each zip code, even tho we only return 1 value at a time
$(long_lat.postalCodes).each(function(k,long_lat_value){
marker_object.push({latLng: [long_lat_value.lat, long_lat_value.lng], name: name});
});
}); // get lat, long for each zip
} // if not empty
}) // foreach location
}); // get zip codes
setTimeout(function(){
console.log( marker_object );
}, 3000);
The end result for the "marker_object" looks something like this when it's finally built
marker_object = [
{latLng: [34.079351, -117.455114], name: 'City 1'},
{latLng: [24.079351, -67.455114], name: 'City 2'},
{latLng: [14.079351, -36.455114], name: 'City 3'},
...
]
How can I tell when my $.getJSON is actually done? because .done() isnt working for me. Should I be using $.AJAX() instead?
Use .ajaxComplete() event.
$(document).ajaxComplete(function(event, xhr, settings) {
alert("Ajax Complete")
});
As per its documentation,
Whenever an Ajax request completes, jQuery triggers the ajaxComplete event. Any and all handlers that have been registered with the .ajaxComplete() method are executed at this time.
Ok, so now I see what you problem is. You want to know when all 30 odd calls have completed. This is simple, just use $.when and .then
passing in all the promises returned by your .getJson
calls.
So you could try something like this:
var myDeferreds = [];
$(locations.nodes).each(function(i, location_value){
var name = location_value.node.city+', '+location_value.node.state+'
'+location_value.node.phone;
var zip = location_value.node.zip;
// if zip is not empty
if(zip != ''){
// get lat, long for each zip
myDeferreds.push($.getJSON( "http://api.geonames.org/postalCodeSearchJSON?postalcode="+zip+"&maxRows=1&username=midnetmedia", function(long_lat){
// loop thru each zip code, even tho we only return 1 value at a time
$(long_lat.postalCodes).each(function(k,long_lat_value){
marker_object.push({latLng: [long_lat_value.lat, long_lat_value.lng], name: name});
}));
}); // get lat, long for each zip
} // if not empty
}) // foreach location
$.when(myDeferreds).then(function() {
console.log("All my ajax calls are complete!!!");
});
Since you're trying to see when all the ajax calls are done (not just when one of them is done), you can compare the count of how many have completed to the total number of request you have and when those counts are equal, then you will know that your array is full and you can use it then. You can do something like this:
var marker_object = [];
// get location zip codes
$.getJSON( "http://localhost/hiab/zip-codes.json").done(function(locations){
// for each zip code
var nodes = $(locations.nodes);
var cnt = 0;
nodes.each(function(i, location_value){
var name = location_value.node.city+', '+location_value.node.state+'
'+location_value.node.phone;
var zip = location_value.node.zip;
// if zip is not empty
if(zip != ''){
// get lat, long for each zip
$.getJSON( "http://api.geonames.org/postalCodeSearchJSON?postalcode="+zip+"&maxRows=1&username=midnetmedia").done(function(long_lat){
// loop thru each zip code, even tho we only return 1 value at a time
$(long_lat.postalCodes).each(function(k,long_lat_value){
marker_object.push({latLng: [long_lat_value.lat, long_lat_value.lng], name: name});
});
// see if all marker nodes are now in the array
if (++cnt === nodes.length) {
// process marker_object array now
}
}); // get lat, long for each zip
} // if not empty
}) // foreach location
}); // get zip codes
Also, there's no need to pass an empty success function when you're using .done()
. You can just leave off that argument and the ajax function will see that the argument is not present.