首页 > PHP资讯 > HTML5培训技术 > jQuery实现的ajax队列(queue)

jQuery实现的ajax队列(queue)

HTML5培训技术

先来看个需求,页面上有2个ajax call。其中一个ajax需要另一个ajax的数据才能操作。如下面这段代码所描述的

$(function(){
        var a_data;
        $.ajax({
                url: "test.php",
                success: function(data){
                        a_data = data;
                },
        });
        $.ajax({
                url: "test.php",
                success: function(data){
                        if(a_data == "5"){
                                //....
                        }
                },
        });
});

第二个ajax的操作,需要等待第一个ajax的数据才能进行。(ps:当然以上写法是错误的,这里只是描述这个需求)

相信不少人都遇到ajax queue 队列的问题。好在自从jquery 1.3以后,有个function能够很好的支持队列,那就是queue。

queue(name)
返回指向第一个匹配元素的队列(将是一个函数数组)

要实现ajax队列,可以将ajax引入queue中。如下代码实现

// 第一个ajax请求
$(document).queue("ajaxRequests", function(){
        //全局变量,储存第一个ajax请求数据
        var a_data;
        $.ajax({
                success: function(data){
                        a_data = data;
                        $(document).dequeue("myName");
                }
        });
});
// 第二个ajax请求
$(document).queue("ajaxRequests", function() {
  $.ajax({
    success: function(data) {
          alert(a_data);
      $(document).dequeue("myName");
    }
  });
});
// 触发queue往下执行
$(document).dequeue("ajaxRequests");

以上代码实现了ajax队列,2个ajax同步执行,其中dequeue用来结束当前ajax,并调用下一个ajax请求。

接下来,我们再来看看另一个ajax 队列的需求(需求二):
在注册的时候验证邮箱、用户名等时候,单个客户端可以频繁发出无数的ajax请求出去,而我们的结果肯定是以最后一个ajax请求为准的。
首先模拟一个服务端页面:

        sleep(5);
        exit(time().'');
?>

然后是前台页面,假设由一个元素触发:
html代码:



        
                
                测试ajax队列
        

        点此触发


<script type="text/javascript" src="http://upload.server110.com/image/20131223/11105H143-0.jpg">《script》
<script type="text/javascript" src="http://upload.server110.com/image/20131223/11105M3E-1.jpg">《script》

JS代码:

$(function(){
        $("body").queue([]);
        $("#dtitle").click(function(){
                $("body").queue(function(){
                        $.get("test.php?t=" + new Date().getMilliseconds(), function(){
                                //这一句让queue往下执行;
                                $("body").dequeue();
                                if ($("body").queue().length == 0)
                                        alert("done");
                        });
                });
        });
});

下面是firebug下的执行结果,我连续对dtitle元素点击三次,如愿每5秒才发送一次请求。当然这只是演示的原理,既然发了三次请求,肯定要以最后一次为准,那么可以通过队列的length属性来轮循,一时length变为0了,就是全部请求结束了,你就可以执行你想要的逻辑了

好了,通过上面的代码,应该对queue的用法和ajax队列有一定了解了。人总是要不断追求完美的,粗矿的代码,并不能提升代码水平。既然队列那么常用,那是否需要将这个功能封装?答案是肯定的。网上也有一些已经封装好了的插件。
那就重写$.ajax 这个方法吧。说干就干:

(function($) {
    var ajax = $.ajax,
        pendingRequests = {},
        synced = [],
        syncedData = [],
        ajaxRunning = [];
    $.ajax = function(settings) {
        // create settings for compatibility with ajaxSetup
        settings = jQuery.extend(settings, jQuery.extend({}, jQuery.ajaxSettings, settings));
        var port = settings.port;
        switch (settings.mode) {
            case "abort":
                if (pendingRequests[port]) {
                    pendingRequests[port].abort();
                }
                return pendingRequests[port] = ajax.apply(this, arguments);
            case "queue":
                var _old = settings.complete;
                settings.complete = function() {
                    if (_old) {
                        _old.apply(this, arguments);
                    }
                    if (jQuery([ajax]).queue("ajax" + port).length > 0) {
                        jQuery([ajax]).dequeue("ajax" + port);
                    } else {
                        ajaxRunning[port] = false;
                    }
                };
                jQuery([ajax]).queue("ajax" + port, function() {
                    ajax(settings);
                });
                if (jQuery([ajax]).queue("ajax" + port).length == 1 && !ajaxRunning[port]) {
                    ajaxRunning[port] = true;
                    jQuery([ajax]).dequeue("ajax" + port);
                }
                return;
            case "sync":
                var pos = synced.length;
                synced[pos] = {
                    error: settings.error,
                    success: settings.success,
                    complete: settings.complete,
                    done: false
                };
                syncedData[pos] = {
                    error: [],
                    success: [],
                    complete: []
                };
                settings.error = function() { syncedData[pos].error = arguments; };
                settings.success = function() { syncedData[pos].success = arguments; };
                settings.complete = function() {
                    syncedData[pos].complete = arguments;
                    synced[pos].done = true;
                    if (pos == 0 || !synced[pos - 1])
                        for (var i = pos; i < synced.length && synced[i].done; i++) {
                        if (synced[i].error) synced[i].error.apply(jQuery, syncedData[i].error);
                        if (synced[i].success) synced[i].success.apply(jQuery, syncedData[i].success);
                        if (synced[i].complete) synced[i].complete.apply(jQuery, syncedData[i].complete);
                        synced[i] = null;
                        syncedData[i] = null;
                    }
                };
        }
        return ajax.apply(this, arguments);
    };
})(jQuery);

以上代码加入了1个mode变量,有3个值”abort”(中止),”queue”(队列),”sync”同步。

对于需求二,我们用这个封装好的ajax改写并改进下,js代码部分如下:

$(function(){
        $("body").queue([]);
        $("#dtitle").click(function(){
                $.ajax({
                        url: "test.php?t=" + new Date().getMilliseconds(),
                        success: function(html){
                                jQuery("ul").append(html);
                        },
                        //用abort而不用queue,是因为需求是需要最后一个ajax request,而之前的ajax request
                        //其实并没有用,那何必要等它们执行完呢?中途就可以把它中止掉
                        mode: "abort"
                });
        });
});

看到这里,相信你已经完全了解ajax队列了。就算不了解,你也可以直接用封装好的那段js代码,直接用mode:“abort”
就可以了。

HTML5培训技术

本文由欣才IT学院整理发布,未经许可,禁止转载。
支持23不支持0