如何保证ajax按你想要的顺序执行

前端的蓬勃发展和要求越来越高的用户体验,使得现在的web页面越来越依赖ajax,无处不在的ajax,无处不在的回调,使得你的代码越写越丑,还容易陷入回调地狱,比如这样:  

$.get('/test', function() {
 
  // do something
  $.get('/test2', function() {
 
    // do something
    $.get('/test3', function() {
 
      // do something
      $.get('/test4', function() {
 
        // do something
        $.get('/test5', function() {
          
        })
      })
    })
  })
});

今天我们的主题是谈谈多个ajax(当然不仅仅是ajax,包括所有的异步操作)的情况,如何能保证预期的执行顺序。

    案例:ajax2 返回的结果需要去匹配ajax1中返回的结果

ajax1返回了如下数据:
 

{
  '10001': '成都',
  '10002': '德阳',
  ...
}

ajax2返回了如下数据:

1
2
3

    

{
  cityCode: '10001'
}

可能一般开发者会这样写:
    

var tempData = null;
// 获取第一个接口的数据
$.get( '/example1', function( data ) {
  tempData = data
} )
// 获取第二个接口的数据
$.get( '/example2', function( data ) {
  // 匹配code
  var cityName = tempData[ data.cityCode ];
  console.log( cityName )
} )

然后你发现好像对了,就这么完成了?多测试几次你就会发现,怎么有时候报错,有时候又正确呢?
那是因为这两个请求都是独立的,互不影响,若接口2响应速度比接口1快,那铁定是要报错的,因为这个时候tempData还未被接口1赋值,仍然是初始化的null,如果你发现了问题,并且有点开发经验那你可能就会这样解决:
 

var tempData = null;
var tempData2 = null;
var cityName = null;
// 获取第一个接口的数据
$.get( '/example1', function( data ) {
  tempData = data;
  if ( cityName === null && tempData2 ) {
    cityName = data[ tempData2.cityCode ];
  }
} )
// 获取第二个接口的数据
$.get( '/example2', function( data ) {
  tempData2 = data;
  // 匹配code
  if ( tempData ) {
    cityName = tempData[ data.cityCode ];
  }
} )

然后便解决了燃眉之急,好接下来,需求变了要求增加一个接口,接口2不仅要去匹配接口1,还要去匹配接口3,甚至更多接口,我们都要这样去写吗。好即使是您很有耐心,也很细心,但是作为程序员,有想过假如有人来维护你的代码,他的心情吗…此处省略一万字

于是jQuery的$.when隆重登场
$.when方法接收不定个deferred类型的对象作为参数



$.when(
        $.ajax( '/example1' ),
        $.ajax( '/example2' ),
        $.ajax( '/example3' )
      ).then( function( data ) {
  // do something
} );

从语法上你可以很清晰的看到注释的地方就是我们三个ajax返回后的回调函数,在这里你可以慢慢地做你基于这三个响应数据任何事,不必担心他们哪个因为响应时间过慢出现报错,你要问我怎么分别拿到三个回调的数据,那我只能说为什么不先尝试以下呢~

好也许你不知道你此时到底要传递多少个ajax进去,3个、4个、5个都有可能,那你一定听说过’apply’方法:
  

var ajaxArray = [ $.ajax( '/example1' ) ];
// 这里或许因为某个条件要添加一个ajax
if ( condition ) {
  ajaxArray.push( $.ajax( '/example2' ) );
}
// 这里或许又因为某个条件要添加一个ajax
if ( condition2 ) {
  ajaxArray.push( $.ajax( '/example3' ) );
}
...
```javascript
$.when.apply( $, ajaxArray ).then( function( data ) {
  // do something
} );

代码是不是干净整洁又大方?比起一堆flag让人容易理解多了,写代码就是拼良心,嗯~

有话要说