ajax异步请求
先来看个简单的ajax异步请求
常规写法
$.ajax({
url:"test.html",
async:true,
success: function(){
doSomething();
}
})
链式写法
.done()
$.ajax({
url:"test.html",
async:true
}).done(function(){
doSomething();
}).fail(function () {
console.log('error...')
})
.then()
$.ajax({
url:"test.html",
async:true
}).then(function(){
doSomething();
},function() {
console.log('error...')
})
多个ajax并发且同一回调函数
假设服务器端有一个查询接口,可以通过商品的ID,查询出商品的详情信息。我要在前端,通过ID来取出商品详情,来展示到前端页面上。因此,写了以下这个方法:
function getData(id){
$.ajax({
url:"../api/getDataByID",
async:true,
id: id
}).then(function(data){
doSomething(data);
},function () {
console.log('error...')
})
}
在以后每次需要获取上面详情时,我只需要使用这个方法,传入商品id,就可以了。
但是,随着需求的变更,需求同时查询出两件不同商品,再进行展示。因此,我对上面的方法进行了改进:
count = 0;
function getData(id){
$.ajax({
url:"../api/getDataByID",
async:true,
id: id
}).then(function(data){
count++;
if(count === 2 ){
doSomething(data);
}
},function () {
console.log('error...')
})
}
增加了一个变量count,在代码中调用两次getData()方法,通过判断变量的值来看是否要执行下一步操作。
但总觉得上面的方法不够灵活,高级,有没更好的办法?
$.when()
通过度娘,我找到了$.when()。
when()方法的参数需要是一个Deferred对象。
关于Deferred对象,这篇文章讲的很详细:https://www.cnblogs.com/tiancai/p/5817996.html
这里简单记录一下:
- Deferred对象: 延迟对象
- Deferred对象有三种执行状态:未完成、已完成和已失败
- Deferred.resolve()方法:
更改执行状态改为已完成。 - Deferred.reject()方法:
更改执行状态改为已失败。
Deferred.promise()方法:
返回一个Deferred对象,它的执行状态继承原先的Deferred对象,并且不能被更改。
有了这些知识点后,还是同样的需求,我对上面的代码进行改进:
function getData(id){
var def = $.Deferred();
$.ajax({
url:"../api/getDataByID",
async:true,
id: id
}).then(function(data){
def.resolve(data);//data 将作为参数传递到Then中.
},function () {
def.reject();
})
return def.promise();
}
$.when(getData(1),getData(2)).then(function(data1,data2) {
doSomething(data1,data2);
},function() {
console.log('error...')
})
在getData()方法中,定义了一个Deferred对象,然后在回调函数中更新对象的状态,最后通过promise()方法返回另一个Deferred对象。
通过when来请求数据,在then方法中,如果两个请求均完成,则调用第一个回调函数;如果其中任意一个失败,则调用第二个回调函数。
$.when.apply 将请求作为数组
在上面的方法中,getData方法有返回的是一个Deferred对象。而我们实际最后要取得是def.resolve(data)中的data数据。我在when方法中放了两个getData,同时在then方法的第一个回调函数中传递了两个参数data1、data2。这个data1、data2分别对应getData(1)和getData(2)返回的数据。
也就是有几个请求,then第一个回调函数中就要写几个参数,感觉还不是很灵活。
能不能把请求塞进数组?
带着这个想法,我又找到了apply。上面的方法再进化,如下:
function getData(id){
var def = $.Deferred();
$.ajax({
url:"../api/getDataByID",
async:true,
id: id
}).then(function(data){
def.resolve(data);//data 将作为参数传递到Then中.
},function () {
def.reject();
})
return def.promise();
}
var defList = [];
defList.push(getData(1));
defList.push(getData(2));
$.when.apply($,defs)
.then(function(data1,data2) {
doSomething(data1,data2);
},function() {
console.log('error...')
})
我先定义了一个数组,然后将请求塞进数组里,然后通过$.when.apply把数组传递进去,测试也是OK。
但是回调函数中,还是得使用data1、data2。不知道这里是否也可以使用数组?这个问题留以后再研究吧。