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

MBa*_*Bax 54 queue ajax jquery

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

看着firebug,我仍然看到我的POST请求同时被触发 - 所以我想知道我是否在错误的地方调用dequeue().

另外 - 我怎样才能获得队列长度?

我需要对这些请求进行排队的原因是,单击按钮会触发它.并且用户可以快速连续点击多个按钮.

试图剥离我的代码的基本结构:

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

}
Run Code Online (Sandbox Code Playgroud)

jAn*_*ndy 87

你的问题在于,它.ajax()会触发异步运行的Ajax请求.这意味着,.ajax()立即返回,非阻塞.所以你的队列功能,但它们几乎会像你描述的那样同时发射.

我不认为这.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);
        }
     };
}());
Run Code Online (Sandbox Code Playgroud)

这远非完美,我只是想展示出去的方式.以上示例可以以类似的方式使用

$(function() {
    ajaxManager.run(); 

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

  • @MBax:我不知道插件,但我总是喜欢自己做事,因为灵活性,知识和冷静:-) (7认同)
  • @MBax:它只是使整个过程保持活力。如果当前没有排队的请求,则它只是空闲的并每秒调用一次。要关闭整个程序,请调用`ajaxManager.stop();`。 (2认同)

dig*_*rld 13

我需要做类似的事情,以为我会在这里发布我的解决方案.

基本上我所拥有的是一个页面,其中列出了所有具有独特标准的货架上的项目.我想逐个加载货架,而不是完全加载一些内容给用户更快,他们可以看到其他内容加载.

基本上我将每个架子的ID存储在JS数组中,我在从PHP调用它时使用它.

然后我创建了一个递归函数,它会在每次调用时弹出数组中的第一个索引,并为弹出的id请求架子.有一次我从响应$.get()$.post()取其我喜欢用我,然后在回调中调用递归函数.

这是代码中的详细说明:

// 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();
Run Code Online (Sandbox Code Playgroud)


小智 8

我使用这个非常简单的代码来保持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));
            }
        })
    });
}
Run Code Online (Sandbox Code Playgroud)

如果您不希望队列自行处理,您可以dequeue从函数中删除它并从另一个函数中调用它.至于获取队列长度,对于这个例子,它将是:

dopostqueue.queue().length
Run Code Online (Sandbox Code Playgroud)


小智 7

我发现上述解决方案有点复杂,而且我需要在发送之前更改请求(更新新数据令牌).

所以我把这个放在一起.资料来源: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);
  }
};
Run Code Online (Sandbox Code Playgroud)

  • 请在此处输入代码(或至少相关部分).据我们所知,github明天可能会失败,永远不会回来,这篇文章将变得毫无意义. (6认同)

小智 7

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

$.when.apply($, arrayOfDeferreds).done(function () {
    alert("All done");
});
Run Code Online (Sandbox Code Playgroud)

  • 你能做一个更完整的例子吗? (4认同)

小智 7

你可以扩展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);
Run Code Online (Sandbox Code Playgroud)

然后使用它像:

$.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
    }       
});
Run Code Online (Sandbox Code Playgroud)

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


Jea*_*ert 5

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 = [];
    },
}
Run Code Online (Sandbox Code Playgroud)

使用:

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