;(function($) { function AjaxQueue(override) { this.override = !!override; }; AjaxQueue.prototype = { requests: new Array(), offer: function(options) { var _self = this; var xhrOptions = $.extend({}, options, { complete: function(jqXHR, textStatus) { if($.isArray(options.complete)) { var funcs = options.complete; for(var i = 0, len = funcs.length; i < len; i++) funcs[i].call(this, jqXHR, textStatus); } else { if(options.complete) options.complete.call(this, jqXHR, textStatus); } _self.poll(); }, beforeSend: function(jqXHR, settings) { if(options.beforeSend) var ret = options.beforeSend.call(this, jqXHR, settings); if(ret === false) { _self.poll(); return ret; } } }); if(this.override) { console.log('go override'); this.replace(xhrOptions); } else { console.log('go queue'); this.requests.push(xhrOptions); if(this.requests.length == 1) { $.ajax(xhrOptions); } } }, replace: function(xhrOptions) { var prevRet = this.peek(); if(prevRet != null) { prevRet.abort(); } this.requests.shift(); this.requests.push($.ajax(xhrOptions)); }, poll: function() { if(this.isEmpty()) { return null; } var processedRequest = this.requests.shift(); var nextRequest = this.peek(); if(nextRequest != null) { $.ajax(nextRequest); } return processedRequest; }, peek: function() { if(this.isEmpty()) { return null; } var nextRequest = this.requests[0]; return nextRequest; }, isEmpty: function() { return this.requests.length == 0; } }; var queue = {}; var AjaxManager = { createQueue: function(name, override) { return queue[name] = new AjaxQueue(override); }, destroyQueue: function(name) { if(queue[name]) { queue[name] = null; delete queue[name]; } }, getQueue: function(name) { return ( queue[name] ? queue[name] : null); } }; $.AM = AjaxManager; })(jQuery); var newQueue = $.AM.createQueue('queue'); $('#ajaxBtn').click(function() { var count = parseInt($(this).attr('data-count')); $(this).attr('data-count', ++count); $(this).html('trigger ajax ' + count); newQueue.offer({ url: '/echo/html/', type: 'post', data: { html: '<p>This is demo ' + count + ' </p>', delay: 3 }, beforeSend: function(jqXHR, settings) { // for whatever reason // var num = Math.floor(Math.random() * 100); // $('#log').append(num); // if(num % 2 !== 0) { // return false; // } }, success: function(data, textStatus, jqXHR) { $('#log').append(data); } }) });
<div id="log"></div> <button id="ajaxBtn" data-count="0">trigger ajax</button>