I have this code that will load css/js/jst (javascript templates) using $.ajax and I’d like to make it run a request after request, running only one at a time, and doing it asynchronously.
var getStuff = function(resources, progressCallback, errorCallback, successCallback, doneCallback){
var deferreds = [];
var deferreds_progressCallback = [];
var len = resources.length;
for(var idx = 0; idx < len; idx++){
var resource = resources[idx];
var dfd = jQuery.Deferred(function(self){
self.notify(resource);
(function(resource){
jQuery.ajax({
cache: false,
url: resource,
dataType: 'text',
error: function(xhr, status, error){
self.reject(resource);
},
success: function(data, status, xhr){
if(typeof(data) != 'string'){
console.log(typeof(data));
}
if(resource.match(/.css$/)){
$('head').append("<style type='text/css'>" + data + "</style>");
}else if(resource.match(/.jst$/)){
var templates_div = jQuery("<div style='display:none;'></div>").appendTo('body');
templates_div.append(data);
}else if(resource.match(/.js$/)){
jQuery.globalEval(data);
}
self.resolve(resource);
}
});
})(resource);
});
deferreds.push(dfd);
deferreds_progressCallback.push(resource);
}
deferreds.reverse();
deferreds_progressCallback.reverse();
(function iterateWhen(){
if(len--){
jQuery.when(deferreds[len])
.then(function(resource){
successCallback(resource);
iterateWhen();
})
.fail(function(resource){
errorCallback(resource);
})
.progress(function(resource){
progressCallback(resource);
});
}else{
doneCallback && doneCallback();
}
}());
}
Right now that code will run all the request at startup. It will wait for the deferred.resolve() to be called, but it won’t wait for the iterateWhen() loop to start iterating over the deferreds[].
According to the jQuery documentation $.Deferred() will accept a function as an optional argument and will run that function before returning from the constructor, so that’s the problem, but I’m not aware of a solution that will do what I want.
Regards!
I finally did it this way:
So you just need to call it like this:
Regards!