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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM