jQuery deferred 使用心得

因为项目的原因,我接触到了jQuery deferred 的这个神奇的工具,下面我用几个例子,与大家分享我的感悟。

我们有5个很耗时的函数 分别为fA、fB、fC、fD、fE  我们的需求是fA和fB同时执行,fA和fB都执行完了,就同时执行fC 和fD ,其中fC和fD只要有一个执行完了,就可以执行fE了。

先完成第一步,写5个函数,并加入deferred

 1 function fA(){
 2         var dtd = $.Deferred();
 3         console.log('fa Start');
 4         setTimeout(function(){
 5             console.log('fa End');
 6             dtd.resolve();
 7         }, 2000);
 8         return dtd.promise();
 9     };
10 
11     function fB(){
12         var dtd = $.Deferred();
13         console.log('fb Start');
14         setTimeout(function(){
15             console.log('fb End');
16             dtd.resolve();
17             
18         }, 3000);
19         return dtd.promise();
20     };
21 
22     /***    fC fD fE 省略  ***/

第二步, fA和fB都执行完了,然后XXX

先给出我的做法,我们需要用到$.when()这个函数  ,先看效果

1     $.when(fA(), fB()).done(function(){
2         console.log('when fA, fB is solved');
3     });

打开控制台:

1 fa Start
2 fb Start
3 fa End
4 fb End
5 when fA, fB is solved

有个问题: $.when()是什么

$.when() ,给出API文档的地址  http://www.css88.com/jqapi-1.9/jQuery.when/

$.when() 就是接受一个或多个deferred(延迟)对象作为参数, 返回一个deferred(延迟)对象,参数中的deferred对象的状态都变成resolve。就将返回值的状态置为resolve。简单来说,就是坚挺多个deferred回调,都成功,就调用成功的回调(dtd.done())我的理解就是一个deferred的异步‘与门’开关。

延伸一下,我们能自己实现一下$.when()吗? 按照刚刚的分析我试了一下,如下:

 1 $.extend({
 2     "myWhen": function(){
 3         var args = arguments;
 4         var dtd = $.Deferred();
 5         var argLen = args.length;
 6         var solveCount = 0;
 7 
 8         var argSolve = function(){
 9             if(solveCount >= (argLen - 1)){
10                 dtd.resolve();
11             }else{
12                 solveCount++;
13             }
14         }
15 
16         $.each(args, function (i_dtd, v_dtd){
17             v_dtd.done(argSolve);
18         });
19 
20         return dtd.promise();
21     }
22 });

调用也改成我们自己的方法:

1 $.myWhen(fA(), fB()).done(function(){
2        console.log('when fA, fB is solved');
3 });

打开控制台:

fa Start
fb Start
fa End
fb End
when fA, fB is solved

看来我们的myWhen 成功了。这个只是我们为了学习而造的轮子,下面的例子还是用$.when()  

第三步,同时执行fC、fD,只要有一个成功就执行fE。

问题来了,$.when是与门开关,那么有没有或门开关呢?好像jquery还真没准备。不过我们有了上面造轮子的经验,相信应该很容易造一个$.myAtLeast()

 1 "myAtLeast": function(){
 2         var args = arguments;
 3         var dtd = $.Deferred();
 4         var hasResolve = false;
 5         var solve = function(){
 6             if(!hasResolve){
 7                 dtd.resolve();
 8             }
 9         };
10         $.each(args, function (i_dtd, v_dtd){
11             v_dtd.done(solve);
12         });
13         return dtd.promise();
14     }

调用一下试试:

1     $.when(fA(), fB()).done(function(){
2         console.log('when fA, fB has resolved');
3         $.myAtLeast(fC(), fD()).done(function(){
4             console.log('fC or fD has resolved');
5             fE();
6         });
7     });

打开控制台: 

 1 fa Start
 2 fb Start
 3 fa End
 4 fb End
 5 when fA, fB has resolved
 6 fC Start
 7 fD Start
 8 fC End
 9 fC or fD has resolved
10 fE Start
11 fD End
12 fE End

我们可以清楚的看到,fC End后, fE就执行了,随后fD才结束。

就此,我们实现了,一开始定义的需求。

写的仓促,望大家指出文章中不对的地方。谢谢!

原文地址:https://www.cnblogs.com/webARM/p/5064141.html