Ajax异步调用的顺序执行

Posted 狐狸姬

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Ajax异步调用的顺序执行相关的知识,希望对你有一定的参考价值。


上次有提到用ajax调用后端接口获取数据,但我最近遇到了一个问题。如果说通过一个接口获取一组列表,列表中的每一个项又要去通过另一个接口查询对应的值,再把第二次得到的值按照第一次获得的列表顺序展现出来,那么应该怎么做呢?

ajax的优点就在于它可以异步调用接口,当一个异步请求发送时,浏览器不会处于锁死、等待的状态,从一个异步请求发送到获取响应结果的期间,浏览器还可以进行其它的操作。但这个特点也意味着如果我们有两个请求,第二个请求需要在第一个请求完成之后执行,这种默认是不行的。因为两个请求的执行是并行的。

我们来举个例子。假设ajax1是从后台请求一组列表,然后我们把列表中的每一项的值alert出来。一般的思路(也可能就我是这样想的,脑子转不过弯来)是在ajax的回调函数中做一个$.each()的遍历,然后在里面写alert。这种情况我这样写应该没什么问题

//接口路径
var
url = "";
//查询关键字
var
keyword = ""; $.ajax({    url: url,    data: {        key: keyword,    },    type: "get",    dataType: "json",    success: function(data) {        
       //这边假设接口给的json格式数据
       //有一个数组是result,        //result里面每一个object有一个key是name        $.each(data.result, function(i, el) {            alert(el.name);        });    },    error: function(data) {        
       console
.log(data);    } });

ajax请求success之后执行的这个函数是在获取到值之后进行的,所以这里alert(el.name)的顺序也是按照获取到的data中的顺序。那如果我们把alert这个操作换掉,我们希望根据每一个el.name去查询address怎么办?这时候我的想法是和上文一样。在alert(el.name)的同样位置调用一个函数,这个函数发起一个新的ajax请求,然后在新的ajax的请求成功回调函数中获取到address。这样做也是可行的。(如果有更好的方法请告诉我~)

//接口路径
var
url = "";
var
urlGetAddress = "";

//查询关键字

var
keyword = ""; $.ajax({    url: url,    data: {        key: keyword,    },    type: "get",    dataType: "json",    success: function(data) {        
       //这边假设接口给的json格式数据
       //有一个数组是result,        //result里面每一个object有一个key是name        $.each(data.result, function(i, el) {            
           //alert(el.name);            getAddress(el.name);        });    },    error: function(data) {        
       console.log(data);    } });

function
getAddress(name)
{    $.ajax({        url: urlGetAddress,        data: {            name: name,        },        type: "get",        dataType: "json",        success: function(data) {            
           //这里是每个name请求一次
           //所以不需要遍历            alert(data.result);        }    }); }

但如果这样写存在问题。每一个name获取address是成功的,但是address的顺序不一定和name的顺序一致。按我们的想法,在第一个ajax遍历结果时我们是按照name的顺序发起第二个ajax请求的。假设name有3个,那么3个分别是按照A,B,C的顺序去请求的。但是B虽然在A之后发起,但是B不会等到A结束再开始。就像两个人跑步,A先开始跑,B在A出发后也开始跑,但是A和B哪个先到终点这是不一定的。如果你不在意A,B,C跑到终点的顺序,只是要这个结果,那请你关掉这篇文章= =。如果我们需要A,B,C到达顺序和出发顺序一致,那我们接着来想想怎么弄。

同步

第一个可能出现的想法是把ajax的async参数改为false。虽然ajax的优点是异步请求,但是也是可以同步的。但是这样在你请求的时候其他js是没办法执行的。对于用户来说就是卡死了。所以这个先放着。

排序

排序这个想法是我现在用的,但是总感觉不太好。既然没有办法控制A,B,C到达终点的顺序,那我们可以在他们到达之后,根据他们的出发顺序进行排序。首先在第一个ajax中我们要记录出发顺序,传递到调用的函数中,然后在第二个ajax的回调中调用排序。假设有一个ul,我们把每一个name放在li里面,然后对li进行排序。

//接口路径
var
url = "";
var
urlGetAddress = "";

//查询关键字

var
keyword = "";
var
html = ""; $.ajax({    url: url,    data: {        key: keyword,    },    type: "get",    dataType: "json",    success: function(data) {        
       //这边假设接口给的json格式数据        //有一个数组是result,        //result里面每一个object有一个key是name        $.each(data.result, function(i, el) {            
           //alert(el.name);            //这边多给一个key用于排序            getAddress(el.name, el.time);        });    },    error: function(data) {        
       console.log(data);    } });

function
getAddress(name, time)
{    Html = "";    $.ajax({        url: urlGetAddress,        data: {            name: name,        },        type: "get",        dataType: "json",        success: function(data) {            
           //这里是每个name请求一次
           //所以不需要遍历            Html +=                
               '<li id="'
+ time +'">' + name +                
               '</li>'
           //把li加到ul            $("ul").html(Html);            
           //调用排序            sortByTime();        },        error: function(data) {            
           console.log(data);        }    }); }

//按照time排序
function sortByTime() {    
   var
arr = $("ul");    arr.sort(function(a, b){      
       return
$(a).attr("id") < $(b).attr("id") ? 1 : -1;    });//对li进行排序    //清空原来ul的内容添加排序后的内容    $("ul").empty().append(arr); }

虽然这个方式在结果上是正确的,做到了展现顺序和请求顺序一致,但是还不够简单。如果有A,B,C,D,E五个,在A请求完成后,A的li加入ul,然后对ul进行排序。接着假设是C完成,那么C的li加入ul,然后对ul进行排序。接着是B完成,那么B的li加入ul,然后对ul进行排序……以此类推。那么5个数据就要排序五次,n个数据排序n次。虽然在数据量小的情况下是没什么问题的,但是量大的话感觉还是有哪里不对。(我还是希望能只排一次,但是自己脑子转不过来,没想到= =,有没有大佬提点想法~)

其他想法

  • 还有一种做法就是后端写接口的直接把两个一起给我们就好啦。干嘛要写两个借口呢~

  • 还有看到什么complete回到函数之类的。这个是不管是success还是error都会执行的,相当于try,catch里面的finally。

  • 还有看到用jquery的when什么的。这个我暂时还没用过,好像是jquery为了解决ajax的回调函数的一些内容。下一次等我试一试,再来和大家聊聊~

以上是关于Ajax异步调用的顺序执行的主要内容,如果未能解决你的问题,请参考以下文章

多个异步ajax请求指定顺序执行

dva 如何把同步改为异步请求

js定时器 settimeout和其他代码是同步执行还是异步执行

JavaScript异步机制

详解Ajax请求——多个异步请求的执行顺序

多个嵌套异步 AJAX 调用和返回数据的顺序