Queue ajax requests using jQuery.queue()

MBax picture MBax · Jan 24, 2011 · Viewed 82.4k times · Source

I am using jQuery.queue() for the first time and haven't quite grasped it. Could someone please point out what I'm doing wrong?

Looking in firebug I am still seeing my POST requests firing at the same time - so I'm wondering if I'm calling dequeue() in the wrong place.

Also - how can I get the queue length?

The reason I need to queue these requests is that it gets fired on click of a button. And its possible for the user to click multiple buttons in quick succession.

Tried to strip out the basic structure of my code:

$("a.button").click(function(){
   $(this).doAjax(params);
});

// method
doAjax:function(params){ 

   $(document).queue("myQueueName", function(){
     $.ajax({
       type: 'POST',
       url: 'whatever.html',
       params: params,
       success: function(data){
         doStuff;

         $(document).dequeue("myQueueName");
       }
     });
   });

}

Answer

jAndy picture jAndy · Jan 24, 2011

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
           }
       });
    });
});