前言
網頁中常常會出現一些耗時比較長的操作,如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 });