作者:阮一峰
連接:http://www.ruanyifeng.com/blog/2012/12/asynchronous%EF%BC%BFjavascript.html
來源:阮一峰的网络日志
異步編成最基本的實踐方法
假設下面有兩個函數
// 要先向服務器請求圖片,請求到之後再儲存
getImg()
saveImg()
假如請求圖片會花很多時間,可以試著用回調函數調用
function getImg(callback){
setTimeout(function () { // 將耗時的程序推延執行
// 請求圖片的代碼
...
callback();
}, 1000);
}
// 執行的代碼就會變以下
getImg(saveImg())
優點:
簡單、容易理解和部署
缺點:
- 不利於代碼的閱讀和維護
- 高度耦合
- 流程很混亂
- 每個任務只能指定一個回調函數。
任務的執行不取決於代碼順序,而取決於某個事件是否發生。
// 監聽getImg是否完成,一但完成及執行saveImg
getImg('done', saveImg)
如此需要改寫getImg函數(這裡借用了jQuery)
function getImg(){
setTimeout(function () {
// 請求圖片的代碼
...
getImg.trigger('done'); // 執行完代碼後觸發'done'事件
}, 1000);
}
優點:
- 可以綁定多個事件
- 每個事件可以指定多個回調函數
- 去耦合
- 利於實現模塊化
缺點:
- 整個程序變成事件驅動型態
- 流程會很不清晰
剛剛提到的事件,可以把理解成信號。
而發布訂閱模式(又稱觀察者模式) 其實就是:
有一個訊號中心,假設某個任務完成,即向訊號中心發布(publish) 一個信號,其他任務可以向任務中心訂閱(subscribe) 訊號。
接下來作者採用Ben Alman的Tiny Pub/Sub(JQuery的一個插件)
// 向訊號中心訂閱getImgDone事件
jQuery.subscribe("getImgDone", saveImg);
// 當執行完getImg發布事件
function getImg(){
setTimeout(function () {
// 請求圖片的代碼
...
jQuery.publish("getImgDone");
}, 1000);
}
當saveImg執行完之後也可以取消訂閱
jQuery.unsubscribe("getImgDone", saveImg);
跟事件監聽比起來較優秀,因為可以透過 "消息中心" ,了解存在多少信號、每個信號有多少訂閱者,從而監控程序的運行( 集中管理的概念 )
之後的篇章會詳談