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 });