如果有多个 ajax 请求需要串行执行(按先后顺序执行),应该怎么办?
使用 jQuery 有多种方式可以实现。

简单实现

(1)嵌套在回调里面

1
2
3
4
5
6
7
8
9
10
11
$.ajax({
    url: "test1.html",
    success: function(){
      alert("哈哈,成功了!");
$.ajax({
     url: "test2.html",
    success: function(){
      alert("哈哈,成功了!");
    },
     });
  });

这种方法的好处是简单直观,但如果请求很多,就会形成“回调地狱”。

(2)使用同步模式

jQuery 里面的同步模式可以保证 ajax 同步进行。代码的顺序,就是 ajax 操作的执行顺序。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
$.ajax({
url: "ajax请求1",
async: false,
success: function (data) {
console.log("ajax请求1 完成");
}
});

$.ajax({
url: "ajax请求2",
async: false,
success: function (data) {
console.log("ajax请求2 完成");
}
});

$.ajax({
url: "ajax请求3",
async: false,
success: function (data) {
console.log("ajax请求3 完成");
}
});

这样避免了回调嵌套。

(3)使用 when 函数

when 函数提供一种方法来执行多个异步操作对象的回调函数,也就是说,可以在多个异步操作放在 when 函数里面,等它们执行完成之后,统一执行回调函数。但是,没法确定这其中多个异步操作的执行顺序。
下面这种写法不能保证先后顺序,当所有 ajax 操作执行完毕之后,就会执行done() 函数里面的内容。

1
2
3
4
5
6
7
$.when(
$.ajax("test1.html"),
$.ajax("test2.html")
).done(function (test1data, test2data) {
alert("哈哈,成功了!");
}
).fail(function () { alert("出错啦!"); });

需要设置 async 参数,才能保证 ajax 操作的先后顺序。

1
2
3
4
5
6
$.when(
$.ajax({async:false,url:"test1.html”}),
$.ajax({async:false,url:"test2.html”})
).done(function(test1data,test2date){
alert("哈哈,成功了!"); }
).fail(function(){ alert("出错啦!"); });

函数递归

当 ajax 操作里面的参数,需要批量生成,而不能事先列举的情况下,我们可以先创建 deffer 对象,放入数组中,然后再遍历这个数组,执行 ajax 操作。

下面的例子演示的是查询设备的数据,设备编号是存储在 diviceIds 数组中的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
//此函数用来生成 deffer 对象
var GetSomeDeferredStuff = function () {
var deferreds = [];
$.each(diviceIds, function (i, v) {
var deviceid = v;
deferreds.push(
$.ajax({
type:'GET',
url:"getedata!parm",
data:{tm1: startm, tm2: endtm, id: deviceid},
dataType:"json"
})
)
});
return deferreds;
};
//执行这个函数,把所有包含 ajax操作的 deffer 对象都放在一个数组里面
var d = GetSomeDeferredStuff();

//使用 when 函数使所有 ajax 操作并行执行,但不能决定其先后顺序。
$.when.apply(null, GetSomeDeferredStuff()).done(function () {
//所有异步数据加载后,开始绘图
DrawChart(seriesData)
});

如果想要所有 ajax 操作 按顺序执行,可以使用函数回调,把下一个 ajax 操作放在上一个 ajax 操作的 done 函数里面执行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//串行执行,按先后顺序来
var action = function(d){
if (d.length == 1){
d[0].done(function(data){
seriesData.push(data)
})
}else{
arr = d.pop(); //从最后一个开始,依次往前
// arr = d.shift(); // 从第一个开始,依次往后
arr.done( function(data){
seriesData.push(data)
action(d);
})
}
};
action(d);

//所有异步数据加载后,开始绘图
DrawChart(seriesData)

这种写法代码简单,结构清晰。