多个ajax异步请求调用同一个回调函数的实现

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。不知道这里是否也可以使用数组?这个问题留以后再研究吧。

本文参考:https://www.cnblogs.com/tiancai/p/5817996.html

猜你喜欢

转载自blog.csdn.net/u012413551/article/details/85221207