假設(shè)一個業(yè)務(wù)場景:
通過rss地址,獲取rss并保存于文件,rss地址保存于文件中。
完成該場景的業(yè)務(wù)需要完成3個任務(wù):
1.從文件中讀取rss地址。
2.獲取rss。
3.保存于文件。
最后將這三個任務(wù)進行整合。
準(zhǔn)備:
存放rss地址的文件,address.txt。
http://programmer.csdn.net/rss_programmer.html
任務(wù)1:
讀取rss地址文件的內(nèi)容并通過callback返回。
任務(wù)2:
通過rss地址get到rss,并通過callback返回錯誤或數(shù)據(jù)。
任務(wù)3:
將rss保存于文件并通過callback返回錯誤。
整合:
上面的代碼是全異步處理,使用最常見的callback處理異步邏輯的返回,好處是標(biāo)準(zhǔn)寫法,大家都能容易接受;壞處是耦合性太強,處理異常麻煩,代碼不直觀,特別是處理業(yè)務(wù)邏輯復(fù)雜和處理任務(wù)多的場景,層層的callback會讓人眼冒金星,代碼難以維護。
Promise/A規(guī)范的實現(xiàn)之一when.js正是針對這樣的問題域。
讓我們來看一下改造后的代碼。
任務(wù)1:
return deferred.promise;
}
return deferred.promise;
}
任務(wù)3:
return deferred.promise;
}
整合:
解釋:
promise/A規(guī)范定義的“Deferred/Promise”模型就是“發(fā)布/訂閱者”模型,通過Deferred對象發(fā)布事件,可以是完成resolve事件,或者是失敗reject事件;通過Promise對象進行對應(yīng)完成或失敗的訂閱。
在Promises/A規(guī)范中,每個任務(wù)都有三種狀態(tài):默認(rèn)(pending)、完成(fulfilled)、失敗(rejected)。
1.默認(rèn)狀態(tài)可以單向轉(zhuǎn)移到完成狀態(tài),這個過程叫resolve,對應(yīng)的方法是deferred.resolve(promiseOrValue);
2.默認(rèn)狀態(tài)還可以單向轉(zhuǎn)移到失敗狀態(tài),這個過程叫reject,對應(yīng)的方法是deferred.reject(reason);
3.默認(rèn)狀態(tài)時,還可以通過deferred.notify(update)來宣告任務(wù)執(zhí)行信息,如執(zhí)行進度;
4.狀態(tài)的轉(zhuǎn)移是一次性的,一旦任務(wù)由初始的pending轉(zhuǎn)為其他狀態(tài),就會進入到下一個任務(wù)的執(zhí)行過程中。
按照上面的代碼。
通過when.defer定義一個deferred對象。
var deferred = when.defer();
異步數(shù)據(jù)獲取成功后,發(fā)布一個完成事件。
deferred.resolve(data);
異步數(shù)據(jù)獲取失敗后,發(fā)布一個失敗事件。
deferred.reject(err);
并且返回Promise對象作為訂閱使用。
return deferred.promise;
訂閱是通過Promise對象的then方法進行完成/失敗/通知的訂閱。
getRssAddress('address.txt')
.then(getRss)
then有三個參數(shù),分別是onFulfilled、onRejected、onProgress
promise.then(onFulfilled, onRejected, onProgress)
上一個任務(wù)被resolve(data),onFulfilled函數(shù)就會被觸發(fā),data作為它的參數(shù).
上一個任務(wù)被reject(reason),那么onRejected就會被觸發(fā),收到reason。
任何時候,onFulfilled和onRejected都只有其一可以被觸發(fā),并且只觸發(fā)一次。
對于處理異常,when.js也提供了極其方便的方法,then能傳遞錯誤,多個任務(wù)串行執(zhí)行時,我們可以只在最后一個then定義onRejected。也可以在最后一個then的后面調(diào)用catch函數(shù)捕獲任何一個任務(wù)的異常。
如此寫法簡單明了。
Promise給異步編程帶來了巨大的方便,可以讓我們專注于單個任務(wù)的實現(xiàn)而不會陷入金字塔厄運,以上代碼僅僅是基本使用,when.js提供的功能遠遠不止本文提到的這些,具體參照官方API。
新聞熱點
疑難解答