javascript---promise應用
在一些現代瀏覽器中已經提供了原生的Promise對象,其遵循Promise/A+標準。在jQuery1.5+,提供了$.Deferred(其可以被轉化為promise對象)。很多知名的架構中,也提供了promise對象。promise對象在javascript中已經是一種很重要的模式,它在解決非同步問題時表現出的優雅,正是javascript所需要的。以下以jQuery中的$.Deferred對象為例,來看一下promise對象是如何處理非同步問題。關於$.Deferred對象,可以到jQuery官網查看,這裡就不贅述了。 一、封裝非同步作業 首先,我們以載入圖片為例,看以下代碼: //載入圖片函數var loadImg = function(url){ var img = new Image() , deferred = $.Deferred() ; img.src = url ; img.onload = function(){ //成功則觸發deferred.resolve deferred.resolve( this ) ; } ; img.onerror = function(e){ //失敗則觸發deferred.reject deferred.reject( e ); } ; //返回promise對象 return deferred.promise() ;} ; //請求圖片var request = loadImg('http://r2.ykimg.com/0515000054AFFC2D6737B343930AFAD6') ; //請求成功request.done(function(img){ //code}) ; //可以註冊多個回調,當請求成功時,會按註冊的順序執行,fail和always也有此性質request.done(function(img){ // code});//請求失敗request.fail(function(){ // code}) ; //請求完畢request.always(function(){ //code}); 以上的代碼,我封裝了圖片載入的操作,將他們委託給$.Deferred,最後產生一個promise返回。使用這樣的方式,相比用對外暴露回調的方式,顯得更乾淨、更清晰。這麼做的另一個更重要的原因是,promise的串連。 二、promise的串連 我們還是以上面圖片載入的代碼為例,來看一下如何做promise的串連,看以下代碼: var request = loadImg('http://b1.hucdn.com/upload/item/1411/13/89613257775992_800x800.jpg') ; request.done(function(img){ //code}) ; //request串連別的promise之後返回的promisevar request3 = request.then(function(img){ //request執行成功時 串連request1 var request1 = loadImg('http://b1.hucdn.com/upload/item/1410/19/29492535741725_800x800.jpg') ; return request1 ;},function(e){ //request執行失敗時 串連request2 var request2 = loadImg('http://b1.hucdn.com/upload/item/1410/19/29492535741725_800x800.jpg') ; return request2 ;}); //request執行並且request1或request2成功執行時request3.done(function(done){ //code}) ; promise對象提供了then的方法,它接受兩個回調:onResolve和onReject,在回調中返回promise,就可以完成promise之間的串連。通過這種方式,可以使非同步作業串列的執行。 同時,jQuery還提供了另外一種串連方式,看代碼: var request = loadImg('http://b1.hucdn.com/upload/item/1412/23/48188827139381_800x800.jpg') ;var request1 = loadImg('http://b1.hucdn.com/upload/item/1412/06/50258594673502_800x800.jpg') ; //通過$.when串連promisevar request2 = $.when(request,request1) ;request2.done(function(img,img){ //code}) ; jQuery中提供了$.when這個函數,它可以接受n個promise對象為參數,它是將promise的執行結果串連在一起。使用這種方式,多個非同步作業可以並存執行。 三、The End 這裡的代碼是以載入圖片為例,同樣的做法可以應用到其他的非同步作業中去。比如jQuery中的$.ajax、$.fn.animate,調用它們返回的就是promise。在node端,也可以把一些非同步作業(讀資料庫、讀檔案等)封裝成promise。繼而對多個promise實現合并的操作,使其串列或者並存執行。 附:deferred對象 deferred除了用於轉化promise對象外,本身也是個很有用的對象。它除了提供像promise對象的那些方法和屬性外,還有notify函數和progress函數,這兩個函數在實現進度條和瀑布流的時候,有很大的用處。 在實現進度條時,resolve和done函數可以用於定義進度條讀取到100%時的觸發時機和觸發邏輯,notify和progress函數可以用於定義進度條在讀取中的觸發時機和觸發邏輯。reject和fail函數可以用於定義進度讀取失敗時的觸發時機和觸發邏輯。 在實現瀑布流時,resolve和done函數可以用於定義當資料已經全部載入到頁面的觸發時機和觸發邏輯,notify和progress函數可以用於定義瀑布流讀取下一頁的觸發時機和觸發邏輯。