使用jQuery.queue()排队ajax请求

我第一次使用jQuery.queue(),并没有完全掌握它。 有人能指出我做错了什么吗?

看着萤火虫我仍然看到我的POST请求在同一时间开火 – 所以我想知道如果我在错误的地方调用dequeue()。

另外 – 我怎样才能得到队列长度? 谢谢!

我需要对这些请求进行排队的原因是,点击一个button会触发它。 用户可以快速连续点击多个button。

试图去掉我的代码的基本结构:

$("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"); } }); }); } 

在此先感谢您的帮助。

你的问题在于, .ajax()激发了一个asynchronous运行的Ajax请求。 这意味着, .ajax()立即返回,非阻塞。 所以你排队的function,但他们几乎会像你所描述的同时开火。

我不认为.queue()是一个有Ajax请求的好地方,它更适合于使用fx methods 。 你需要一个简单的经理。

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

这是远远不够完美,我只是想展示的路要走。 上面的例子可以用于像

 $(function() { ajaxManager.run(); $("a.button").click(function(){ ajaxManager.addReq({ type: 'POST', url: 'whatever.html', data: params, success: function(data){ // do stuff } }); }); }); 

我需要做一个类似的事情,所以认为我会在这里发布我的解决scheme。

基本上我所得到的是一个列出所有具有独特标准的货架上的项目的页面。 我想一个接一个地加载货架,而不是一个一个地加载货架上的内容给用户,这样他们就可以看到其余的内容。

基本上我把每个货架的ID存储在一个JS数组中,我使用它从PHP中调用它们。

然后我创build了一个recursion函数,每次调用它时,都会将第一个索引从数组中popup,并请求popup的ID的架子。 一旦我有$.get()$.post()无论我喜欢使用我的回应,然后调用callback内的recursion函数。

以下是代码中的细节:

 // 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(); 

我需要为未知数量的ajax调用执行此操作。 答案是推入每个数组,然后使用:

 $.when.apply($, arrayOfDeferreds).done(function () { alert("All done"); }); 

我发现上面的解决scheme有点复杂,另外我需要在发送之前改变请求(以更新新的数据令牌)。

所以我把这个放在一起 来源: https : //gist.github.com/2470554

 /* Allows for ajax requests to be run synchronously in a queue Usage:: var queue = new $.AjaxQueue(); queue.add({ url: 'url', complete: function() { console.log('ajax completed'); }, _run: function(req) { //special pre-processor to alter the request just before it is finally executed in the queue req.url = 'changed_url' } }); */ $.AjaxQueue = function() { this.reqs = []; this.requesting = false; }; $.AjaxQueue.prototype = { add: function(req) { this.reqs.push(req); this.next(); }, next: function() { if (this.reqs.length == 0) return; if (this.requesting == true) return; var req = this.reqs.splice(0, 1)[0]; var complete = req.complete; var self = this; if (req._run) req._run(req); req.complete = function() { if (complete) complete.apply(this, arguments); self.requesting = false; self.next(); } this.requesting = true; $.ajax(req); } }; 

我使用这个非常简单的代码来保持Ajax调用不会互相“超车”。

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

如果你不想让队列自己处理,你可以从函数中移除出dequeue并从另一个函数中调用它。 至于获得队列长度,这个例子是:

 dopostqueue.queue().length 

另一个版本的jAndy的答案,没有计时器。

 var ajaxManager = { requests: [], addReq: function(opt) { this.requests.push(opt); if (this.requests.length == 1) { this.run(); } }, removeReq: function(opt) { if($.inArray(opt, requests) > -1) this.requests.splice($.inArray(opt, requests), 1); }, run: function() { // original complete callback oricomplete = this.requests[0].complete; // override complete callback var ajxmgr = this; ajxmgr.requests[0].complete = function() { if (typeof oricomplete === 'function') oricomplete(); ajxmgr.requests.shift(); if (ajxmgr.requests.length > 0) { ajxmgr.run(); } }; $.ajax(this.requests[0]); }, stop: function() { this.requests = []; }, } 

使用:

 $(function() { $("a.button").click(function(){ ajaxManager.addReq({ type: 'POST', url: 'whatever.html', data: params, success: function(data){ // do stuff } }); }); }); 

learn.jquery.com网站也有一个很好的例子 :

 // jQuery on an 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 invoke the next event in the queue ajaxOpts.complete = function() { // Invoke the original complete if it was there if (oldComplete) { oldComplete.apply(this, arguments); } // Run the next query in the queue next(); }; // Run the query $.ajax(ajaxOpts); }); }; // Get each item we want to copy $("#items li").each(function(idx) { // Queue up an ajax request $.ajaxQueue({ url: "/ajax_html_echo/", data: { html: "[" + idx + "] " + $(this).html() }, type: "POST", success: function(data) { // Write to #output $("#output").append($("<li>", { html: data })); } }); }); 

你可以扩展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); 

然后像这样使用它:

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

当然你可以使用任何其他$ .ajax选项,比如type,data,contentType,DataType,因为我们正在扩展$ .ajax

我也必须在我的解决scheme中做到这一点,我发现我可以这样做:

 //A variable for making sure to wait for multiple clicks before emptying. var waitingTimeout; $("a.button").click(function(){ $(this).doAjax(params); clearTimeout(waitingTimeout); waitingTimeout = setTimeout(function(){noMoreClicks();},1000); }); // method doAjax:function(params){ $(document).queue("myQueueName", function(next){ $.ajax({ type: 'POST', url: 'whatever.html', data: params, contentType: "application/json; charset=utf-8", dataType: "json", success: function(data){ doStuff; next(); }, failure: function(data){ next(); }, error: function(data){ next(); } }); }); } function noMoreClicks(){ $(document).dequeue("myQueueName"); } 

通过使用在队列函数中传递的next()callback,您可以使下一个操作出列。 所以通过将下一个放在ajax的处理器中,可以使ajax调用与浏览器和浏览器的渲染或绘制线程asynchronous,但使它们彼此同步或序列化。

这是一个非常基本的例子。 在例子小提琴。 点击一下button,等待一秒钟。 你会看到超时触发和单个操作发生。 然后点击button尽可能快(或者超过一秒),你会看到所有的时间,你点击button,操作排队,然后只有等待一秒后,他们击中了页面和淡入后另一个。

这样做的好处是,如果队列已经清空,那么在清空时添加到它的任何操作都会放在最后,然后在时间到了时才处理。

这是我的解决scheme,我用它来产生一些Browsergame的请求队列。 如果发生任何事情,我会停止这个队列,并完成一些特殊的最后请求或清理工作。

 var get_array = ["first", "second", "third"]; var worker = $("<div />"); // to line up requests in queue $.queuedAjax = function(args){ // add up requests for me worker.queue( function(next){ $.ajax(args).always(next); } ); }; $.queuedSomething = function(){ // add up something special for me worker.queue( function(next){ //worker.clearQueue(); //worker = $("<div />"); //cleanup for next .each //maybe another .each } ); }; $.each( get_array , function( key , value ) { $.queuedAjax({ type: 'GET', url: '/some.php?get='+value, dataType: 'text', success: function(sourcecode){ if (sourcecode.match(/stop your requests, idiot!/)) { worker.clearQueue().queue($.queuedSomething); alert(' the server told me to stop. i stopped all but not the last ´$.queuedSomething()´ '); } } }); }); $.queuedSomething(); 

我有一个类似的问题,

如果没有向你导入ajax-call是asynchronous的(即使这是ajax的“a”),你可以简单地告诉jQuery做ajax请求而不是asynchronous。 这对我工作,并没有带来需要更大的解决方法。

  $.ajax({ ... async: false }); 

我应该提到,这是从jQuery 1.8以来不赞成使用,它不会与dataType:'jsonp'。