You problem here is, that .ajax()
fires an asyncronous running Ajax request. That means, .ajax()
returns immediately, non-blocking. So your queue the functions but they will fire almost at the same time like you described.
I don't think the .queue()
is a good place to have ajax requests in, it's more intended for the use of fx methods
. You need a simple manager.
var ajaxManager = (function() {
var requests = [];
return {
addReq: function(opt) {
requests.push(opt);
},
removeReq: function(opt) {
if( $.inArray(opt, requests) > -1 )
requests.splice($.inArray(opt, requests), 1);
},
run: function() {
var self = this,
oriSuc;
if( requests.length ) {
oriSuc = requests[0].complete;
requests[0].complete = function() {
if( typeof(oriSuc) === 'function' ) oriSuc();
requests.shift();
self.run.apply(self, []);
};
$.ajax(requests[0]);
} else {
self.tid = setTimeout(function() {
self.run.apply(self, []);
}, 1000);
}
},
stop: function() {
requests = [];
clearTimeout(this.tid);
}
};
}());
This is far away from being perfect, I just want to demonstrate the way to go. The above example could be used in a way like
$(function() {
ajaxManager.run();
$("a.button").click(function(){
ajaxManager.addReq({
type: 'POST',
url: 'whatever.html',
data: params,
success: function(data){
// do stuff
}
});
});
});
I needed to do a similar thing so thought I'd post my solution here.
Basically what I've got is a page which lists projects on shelves which all have distinctive criteria. I wanted to load the shelves one by one rather than altogether to get some content to the user quicker which they could look at whilst the rest loads.
Basically I stored the ID of each shelf in a JS array which I use when calling them from PHP.
I then created a recursive function which will pop the first index out of the array each time its called and request the shelf for the popped id. Once I have the response from the $.get()
or $.post()
whichever I prefer to use I then call the recursive function from within the callback.
Here's an elaboration in code:
// array of shelf IDs
var shelves = new Array(1,2,3,4);
// the recursive function
function getShelfRecursive() {
// terminate if array exhausted
if (shelves.length === 0)
return;
// pop top value
var id = shelves[0];
shelves.shift();
// ajax request
$.get('/get/shelf/' + id, function(){
// call completed - so start next request
getShelfRecursive();
});
}
// fires off the first call
getShelfRecursive();
I use this very simple code to keep ajax calls from "overtaking" each other.
var dopostqueue = $({});
function doPost(string, callback)
{
dopostqueue.queue(function()
{
$.ajax(
{
type: 'POST',
url: 'thephpfile.php',
datatype: 'json',
data: string,
success:function(result)
{
dopostqueue.dequeue();
callback(JSON.parse(result));
}
})
});
}
If you don't want the queue to handle itself, you can just remove the dequeue
from the function and call it from another function.
As to getting the queue length, for this example it would be:
dopostqueue.queue().length
you could extend jQuery:
(function($) {
// Empty object, we are going to use this as our Queue
var ajaxQueue = $({});
$.ajaxQueue = function(ajaxOpts) {
// hold the original complete function
var oldComplete = ajaxOpts.complete;
// queue our ajax request
ajaxQueue.queue(function(next) {
// create a complete callback to fire the next event in the queue
ajaxOpts.complete = function() {
// fire the original complete if it was there
if (oldComplete) oldComplete.apply(this, arguments);
next(); // run the next query in the queue
};
// run the query
$.ajax(ajaxOpts);
});
};
})(jQuery);
then use it like:
$.ajaxQueue({
url: 'doThisFirst.php',
async: true,
success: function (data) {
//success handler
},
error: function (jqXHR,textStatus,errorThrown) {
//error Handler
}
});
$.ajaxQueue({
url: 'doThisSecond.php',
async: true,
success: function (data) {
//success handler
},
error: function (jqXHR,textStatus,errorThrown) {
//error Handler
}
});
of course you can use any of the other $.ajax options like type, data, contentType, DataType since we are extending $.ajax
I needed to do this for an unknown number of ajax calls. The answer was to push each into an array and then use:
$.when.apply($, arrayOfDeferreds).done(function () {
alert("All done");
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With