jQuery中的$.Deferred、$.when异步操作

前言
  网页中常常会出现一些耗时比较长的操作,如ajax请求服务器数据,这些操作都不能立即得到结果。如果我们需要在这些操作执行完后来进行另外的操作,我们就需要将这些操作放在回调函数中,$.Deferred就是jQuery用来处理回调操作的。jQuery中的$.Deferred对$.Callbacks很有依赖,看看$.Callbacks执行回调。
1     var callbacks = $.Callbacks();
2     setTimeout(function(){
3         console.log(1); // 1
4         callbacks.fire(); // 2 add中的方法也会执行(同步的写法,异步执行)
5     }, 1000);
6     callbacks.add(function(){
7         console.log(2);
8     });

  $.Deferred来实现上面的操作

1     var deferred = $.Deferred();
2     setTimeout(function(){
3         console.log(1); // 1
4         deferred.resolve();// 2
5     }, 1000);
6     deferred.done(function(){
7         console.log(2);
8     });
$.Deferred的三队抽象
1、resolve-》done-》$.Callbacks('once memory')-》成功-》只触发一次
2、reject-》fail-》$.Callbacks('once memory')-》失败-》只触发一次
3、notify-》progress-》$.Callbacks('memory')-》通知-》不断触发直到resolve或reject
 1     var deferred = $.Deferred();
 2     setTimeout(function(){
 3         //deferred.resolve(); // success
 4         deferred.reject(); // error
 5         //deferred.notify(); // progressing
 6     }, 1000);
 7     deferred.done(function(){
 8         console.log('success');
 9     }).fail(function(){
10         console.log('error');
11     }).progress(function(){
12         console.log('progressing');
13     });

下面是一个比较有意思的用法:memory的记忆功能。

 1     var deferred = $.Deferred();
 2     setTimeout(function(){
 3         deferred.resolve();// 1
 4     }, 100);
 5     deferred.done(function(){
 6        console.log(1);
 7     });
 8     $('#btn').on('click', function () {
 9         deferred.done(function(){
10             console.log(2); // 2...只要单击一次按钮就会触发一次
11         });
12     });
deferred和promise
  $.Deferred会有两个延迟对象,分别是deferred和promise。deferred包含有所有的方法,而promise不包含改变延迟对象状态的三个方法resolve、reject、notify。这样做的好处就是在某些时候对外不提供改变对象状态的方法,以免延迟对象的状态混乱。
 1     function fn(){
 2         var deferred = $.Deferred();
 3         setTimeout(function(){
 4             deferred.resolve();// 不会触发,状态在外部被修改了。
 5         });
 6         return deferred;
 7     }
 8     var newDeferred = fn();
 9     newDeferred.done(function(){
10         console.log('success');
11     }).fail(function(){
12         console.log('error');
13     });
14     newDeferred.reject(); // error
 1     function fn(){
 2         var deferred = $.Deferred();
 3         setTimeout(function(){
 4             deferred.resolve();// success
 5         });
 6         return deferred.promise();
 7     }
 8     var newDeferred = fn();
 9     newDeferred.done(function(){
10         console.log('success');
11     }).fail(function(){
12         console.log('error');
13     });
14     newDeferred.reject(); // 报错 reject方法不存在
其他方法介绍
1、state:返回延迟对象的状态
  pending:创建对象时的状态
  resolved:回调成功-会禁用失败和notify的回调
  rejected:回调失败-会禁用成功和notify的回调
2、always:不管成功或失败都会触发
3、then:传递三个方法分别处理三个操作
4、pipe:延迟对象过滤器?
resolve、done、reject、fail、notify、progress
$.when
1、$.when(deferred):一个延迟对象。
2、$.when(deferred, deferred,...):多有的延迟对象都调用了resolve()时才执行done;只要有一个延迟对象调用了reject()就会执行fail()。
 1     function fn1(){
 2         var deferred = $.Deferred();
 3         setTimeout(function(){
 4             deferred.resolve();
 5         }, 1000);
 6         return deferred.promise();
 7     }
 8     function fn2(){
 9         var deferred = $.Deferred();
10         setTimeout(function(){
11             deferred.resolve();
12         }, 1000);
13         return deferred.promise();
14     }
15     $.when(fn1(), fn2()).done(function(){
16         console.log('success'); // 都resolve() success
17     }).fail(function(){
18         console.log('error'); // 有一个reject() error
19     });
 3、如果参数不是延迟对象就会跳过该参数并代表成功,如果参数都不是延迟对象,也会成功,会执行done。
 1     function fn1(){
 2         var deferred = $.Deferred();
 3         setTimeout(function(){
 4             deferred.resolve();
 5         }, 1000);
 6         return deferred.promise();
 7     }
 8     $.when(fn1(), 123).done(function(){
 9         console.log('success'); // fn1()->resolve() success
10     }).fail(function(){
11         console.log('error'); // fn1()->reject() error
12     });

NOTE:成功或失败的回调函数的参数对应when中的参数,如果参数是延迟对象回调函数得到undefined,不是延迟对象得到参数值。

 1     function fn1(){
 2         var deferred = $.Deferred();
 3         setTimeout(function(){
 4             deferred.resolve();
 5         }, 1000);
 6         return deferred.promise();
 7     }
 8     $.when(fn1(), 123).done(function(arg1, arg2){
 9         console.log(arg1);// undefined
10         console.log(arg2);//123
11         console.log('success'); // fn1()->resolve() success
12     }).fail(function(){
13         console.log('error'); // fn1()->reject() error
14     });
原文地址:https://www.cnblogs.com/tyxloveyfq/p/4309929.html