1

I have a function which is passed a list of URLs (in this case a list of json files) that makes asynchronous ajax calls for each resource, and once they are done returns a single object with the contents.

function loadModels(modelList){
    var modelObject = {}

    for(model in modelList){
        var urlPath = modelList[model].indexOf(".json") > -1 ? 'model/'+modelList[model]+'json' : 'model/'+modelList[model]+'.json';
        $.ajax(urlPath).done(function(jsonData){
            modelObject[modelList[model]] = jsonData;
        });
    }   

    console.log(modelObject);
    return modelObject;
}

Trouble is, the console always logs Object{} since the function returns before the deferred objects resolve. If I set async: false then it works just fine, but I don't want the requests to wait for each other.

How can I force the function to wait before returning and still make calls asynchronously?

EDIT: The deferred solution in the link isn't a complete enough answer. The issue I was running into was related to closures. Here's the working code block:

function loadModels(modelList, callback){
var promises = [];

for(model in modelList){
    (function(){
        var currentModel = modelList[model];
        var urlPath = currentModel.indexOf(".json") > -1 ? 'model/'+currentModel+'json' : 'model/'+currentModel+'.json';
        var promise = $.ajax(urlPath);
        log('pulling model: ' + currentModel);
        promise.done(function(jsonData){
            modelObject[currentModel] = jsonData;
            log('model pulled: ' + currentModel);
        });
        promises.push(promise);
    })();
}

$.when.apply(null, promises).done(function() {
    callback(modelObject);
});
}
myrcutio
  • 1,045
  • 9
  • 13

2 Answers2

2

You can use jQuery.when() to wait for all the promises to resolve before continuing...

var promises = [];

for(model in modelList){
    var urlPath = modelList[model].indexOf(".json") > -1 ? 'model/'+modelList[model]+'json' : 'model/'+modelList[model]+'.json';
    var promise = $.ajax(urlPath);
    promises.push(promise);
    promise.done(function(jsonData){
        modelObject[modelList[model]] = jsonData;
    });
}   

$.when.apply(null, promises).done(function() {
    console.log(modelObject);
});
Anthony Chu
  • 37,170
  • 10
  • 81
  • 71
  • I suspected it involved using when but I couldn't make the connection to also use apply after the loop finished. Thanks for the example! – myrcutio Apr 28 '14 at 14:32
0

when the last ajax-done event is finished trigger an event and pass your object to the event data

and where you need the data handle that event.

$.event.trigger({
            type: "afterMyAjaxDone",
            data: MyDataObject
        });

$(document).on('afterMyAjaxDone', function (e) {
    var MyDataObject = e.data;
}
Exlord
  • 5,009
  • 4
  • 31
  • 51