先来看个需求,页面上有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了,就是全部请求结束了,你就可以执行你想要的逻辑了
好了,通过上面的代码,应该对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”
就可以了。