-1

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+'\n'+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?

bghouse
  • 558
  • 2
  • 8
  • 26
  • 1
    The second argument to your `$.getJson` is a function called on success (i.e. when done). Why don't you put your code there? If you are not using it, don't pass an empty function, just leave it out altogether. – Matt Burland Jan 24 '14 at 20:45
  • 1
    You're passing a callback function that does nothing... just use that. – Jasper Jan 24 '14 at 20:45
  • More to the point, what makes you think `done` isn't being called? In this [fiddle](http://jsfiddle.net/s5g4t/) both the success and done both get called just fine. – Matt Burland Jan 24 '14 at 20:48
  • 1
    if `done` isn't working, your success callback isn't either. Add a fail callback to see why the done isn't running. – Kevin B Jan 24 '14 at 20:49
  • http://stackoverflow.com/a/18425082/1385672 – wirey00 Jan 24 '14 at 20:51

3 Answers3

0

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.

Venkata Krishna
  • 14,926
  • 5
  • 42
  • 56
  • I tried: `$(document).ajaxComplete(function(){ console.log( marker_object ); });` But instead of 30 objects like i was returning, it returns hundreds of objects instead. This function would probably work better if I only had 1 ajax call, but I have 2 calls happening. – bghouse Jan 24 '14 at 20:54
  • @bghouse - right. This is a generic solution. But you could differentiate between each request by using the params `xhr` or `xhr.responseHTML` – Venkata Krishna Jan 24 '14 at 21:02
0

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+'\n'+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!!!");
});
Matt Burland
  • 44,552
  • 18
  • 99
  • 171
0

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+'\n'+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.

jfriend00
  • 683,504
  • 96
  • 985
  • 979