兼容IE大佬的异步流程控制大法

其实工作中一直都有异步流程控制的需求,主要是各种需要顺序执行的AJAX。

之前请求不多的时候,我就直接简单粗暴地在回调里调用下一个请求函数,随着项目越来越大,越来越复杂,这种方式难以维护的缺点就越发的明显。大热的ES6中的promise方法的确很强,然而,需要兼容IE7(现在是IE10了)的我流下了两行清泪....而且我们项目还未引入打包和配置工具(没错就是这么落后),所以没有办法愉快地使用Promise等ES6语法和对象。

这个问题一直非常困扰我,想了很久都没有比较好的解决办法,直到有一天,看到了一个CSS3动画的制作,依赖JQ,控制异步动画的时候完全使用了deferred对象,仿佛打开了异步流程新世界的大门

deferred对象的使用方法

  1. 创建Deferred对象
  2. 在异步流程结束后改变deferred对象状态
  3. 返回deferred对象
function F(){
    var def = $.Deferred();  //创建deferred对象
    setTimeout(function(){
        console.log("hi~");
        def.resolve();    //改变deferred对象状态为“已完成”
    },50);
    return def; //返回deferred对象
}

然后在需要的地方调用这个异步函数,使用then表示该方法执行完后再执行下一步

F().then(function(){
    //do something you want
});

恩,妈妈再也不用担心我的异步了,即便是有多个异步回调需要控制,也能使用连续的then写出漂亮的顺序流

F1().then(function(){
    F2();
}).then(function(){
    F3();
});

似乎回调依赖的问题已经解决了,直到有一天,我遇到了一个循环异步回调

一个流程依赖多个异步回调

大致需求是,有一个循环体,里面的循环内容是异步流程,大概可以写成这样


 for(var i = 0 ;i < 10 ; i++){
        setTimeout(function(){
            console.log("我要吃饭啦~"+i);
        });
    }
 console.log("我吃饱啦~")

promise对象里有个all,可以用放入数组的形式控制多个异步依赖,没有编译工具又要保证兼容性的我再次留下两行清泪。。研究了半天,好像没有在Deferred对象中发现有类似的方法。

于是先是尝试着,还是使用单个流程控制的方法去写

function wait(){
    var deferred = $.Deferred();
     for(var i = 0 ;i < 10 ; i++){
        setTimeout(function(){
            console.log("我要吃饭啦~"+i); 
            deferred.resolve();
        });
    }
    return deferred;
}

wait().then(function(){
    console.log("我吃饱啦~")
})

emmmmm当然这是不对的了,循环第一次的时候,deferred状态就已经更改为完成,所以就会执行“我吃饱啦”,然后再继续执行剩余的9次。

image.png

于是,我做了如下改写,使用变量count作为计数标识,当计数循环完成之后,再改变deferred对象的状态。

function wait(){
  var dtd = $.Deferred()
   var count = 0;
     for(var i = 0 ;i < 10 ; i++){
        setTimeout(function(){
            console.log("我要吃饭啦~"+i); 
            count++;
            if( count == 10 ){
                 dtd.resolve();
            }
        },500);
    }
    return dtd;
}
wait().done(function(){console.log("我吃饱啦")})

运行10次“我要吃饭啦”,随后运行“我吃饱啦”

image.png

成功啦~给自己一朵小红花!

兼容性测试

最后的最后,在IE的各个环境下进行测试,居然在IE5下也能跑。所以只要是能支持JQ的Deferred对象,一般情况下这种异步流程操作方式都是可行的。

ps:感觉自己是走了歪门邪道,不知道deferred对象中是不是有类似于promise对象中的all可以直接控制多个异步,如果有的话,还希望各位大大能指点迷津

pss:关于公司还是使用非常传统开发方式的问题,只能说上有政策的阻碍,下有业务的局限。原因很复杂,一时半会儿也说不清,所以只能找机会跑路啦哈哈哈哈

学习资料:
jQuery的deferred对象详解——阮一峰

你可能感兴趣的:(兼容IE大佬的异步流程控制大法)