John Cena John Cena - 2 months ago 7
Ajax Question

Promises with ajax

I've got this bit of code right now, where I get all the templates I need for a page.

Problem is that this way the ajax requests doesn't finish in the same order every time I load the page.

Is there a way to use promises or something else so that the load order always stays the same?

Thanks.

var loadTemplates = function (templatesObject) {
$.each(templatesObject.template, function (index, template) {
template.callback = template.callback || $.noop;

$.ajax({
url: template.url,
success: function(html) {
var compiledHtml = Handlebars.compile(html);
var output = compiledHtml(template.data);
$(template.target).append(output);
template.callback();
}
});
});
};


Edit: This is how my object looks like, with varying amounts of templates, just 2 in this instance.

templatesObject

var templates = {
template: [
{
url: 'firsturl',
target: '#page-content'
},
{
url: 'myurl',
target: '#page-content',
data: data,
callback: awesomefunction
}
]
};

Answer

You could use the fact that $.ajax returns a promise, use $.map instead of $.each, and use $.when to wait for all the ajax to complete, and do what you do in the success callback in the $.when().then callback ...

var loadTemplates = function (templatesObject) {
    $.when.apply($, $.map(templatesObject.template, function (index, template) {
        template.callback = template.callback || $.noop;
        return $.ajax({
            url: template.url,
        }).then(function(html) {
            return {html: html, template: template};
        });
    })).then(function() {
        $.each(arguments, function(index, result) {
            var compiledHtml = Handlebars.compile(result.html);
            var output = compiledHtml(result.template.data);
            $(result.template.target).append(output);
            result.template.callback();
        })
    });
};