0

I'm trying to loop thru an array of teams to get player data and pass the data to an object. My ajax call gets the files. After looping thru all teams I then want to write a log with the data collected. The problem is that writeLog() is called immediately - I think - not waiting for the loop to finish. Is this a hoisting problem? A callback issue? How can I refactor my code to writeLog() after for loop is finished?

(function(){

$('#generate-report').on('click', function(){

    var logObj = {
        playerCount: 0,
        firstNameArray: [],
        lastNameArray: [],
        firstNameCharCount: 0,
        lastNameCharCount: 0,
        resultFirst: 0,
        resultLast: 0,
        freqReportFirst: "First name\n",
        freqReportLast: "Last name\n",
        freqObjFirst: {},
        freqObjLast: {},        
    }

    var url = "http://feeds.nfl.com/feeds-rs/roster/";

    var teams = new Array("3800", "0200", "0325", "0610", "0750", "0810", "0920", "1050",
                          "1200", "1400", "1540", "1800", "2120", "2200", "2250", "2310",
                          "2700", "3000", "3200", "3300", "3410", "3430", "2520", "3700",
                          "3900", "4400", "4600", "4500", "2510", "4900", "2100", "5110"
                                      );
    //var teams = new Array("3800");  // For testing

    for(var i=0; i<teams.length; i++){
        console.log(teams[i]);
        $.ajax({
            url: url + teams[i] + ".json",
            type: 'GET',
            success: function(response){
                processPlayerNames(response, logObj);
            },
            error: function(response){
                console.log(response);
            }
        });
    };   

    writeLog(logObj);

});

})();

sbaden
  • 555
  • 3
  • 16
  • 30

1 Answers1

1

$.ajax() returns results asynchronously. You can push $.ajax() call to an array, then use Promise.all(), .map() on array of promise objects, or use $.when(), Function.prototype.apply(), .map() to perform all asynchronous tasks before calling writeLog() at .then() chained to variable representing jQuery promise object returned from $.when() call.

var requests = $.when.apply(null, teams.map(function(team) {
  return $.ajax({
            url: url + team + ".json",
            type: 'GET',
            success: function(response){
                processPlayerNames(response, logObj);
            }
        });
}));

requests.then(function() {
  writeLog(logObj)
}, function(response){
  console.log(response);
});
guest271314
  • 1
  • 15
  • 104
  • 177
  • Not sure I understand completely - is it strictly an ajax thing? – sbaden Oct 04 '16 at 00:19
  • No, it's a "how to deal with asynchronous code" thing – Jaromanda X Oct 04 '16 at 00:22
  • @sbaden `$.ajax()` returns results asynchronously. `for` loop executes `$.ajax()` without wait for previous call to complete. `writeLog()` could be called before one or more of the `$.ajax()` calls have complete. See [How do I return the response from an asynchronous call?](http://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call?) – guest271314 Oct 04 '16 at 00:24
  • Appreciate the explanation and link @guest271314 – sbaden Oct 04 '16 at 00:50
  • Is the function(response){ console.log(response);} in place of the original ajax error: function(response){ console.log(response)} ? – sbaden Oct 04 '16 at 01:04
  • @sbaden Yes. If any of the `$.ajax()` requests returns an error, or rejected jQuery promise, the error handler should be called. You could alternatively handle error within `.map()`, see [Why is onRejected not called following Promise.all() where Promise.reject() included in array passed to Promise.all()?](http://stackoverflow.com/questions/35042068/why-is-onrejected-not-called-following-promise-all-where-promise-reject-incl) – guest271314 Oct 04 '16 at 01:07