jQuery实现的ajax队列(queue)

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

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
$( 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中。如下代码实现

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
// 第一个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请求为准的。
首先模拟一个服务端页面:

1
2
3
4
<?PHP
     sleep(5);
     exit (time(). '' );
?>

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

01
02
03
04
05
06
07
08
09
10
11
12
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
< html xmlns = "http://www.w3.org/1999/xhtml" >
     < head >
         < meta http-equiv = "Content-Type" content = "text/html;charset=utf-8" />
         < title >测试ajax队列</ title >
     </ head >
< body >
     < div id = "dtitle" >点此触发</ div >
</ body >
< script type = "text/javascript" src = "http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js" ></ script >
< script type = "text/javascript" src = "test.js" ></ script >
</ html >

JS代码:

01
02
03
04
05
06
07
08
09
10
11
12
13
$( 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了,就是全部请求结束了,你就可以执行你想要的逻辑了
201012242252113764 jQuery实现的ajax队列(queue)

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

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
( 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代码部分如下:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
$( 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”
就可以了。

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值