javascript非同步程式設計幾種方法簡介
“同步模式”就是上一段的模式,後一個任務等待前一個任務結束,然後再執行,程式的執行順序與任務的排列順序是一致的、同步的;“非同步模式”則完全不同,每一個任務有一個或多個回撥函式(callback),前一個任務結束後,不是執行後一個任務,而是執行回撥函式,後一個任務則是不等前一個任務結束就執行,所以程式的執行順序與任務的排列順序是不一致的、非同步的。
“非同步模式”非常重要。在瀏覽器端,耗時很長的操作都應該非同步執行,避免瀏覽器失去響應,最好的例子就是Ajax操作。在伺服器端,“非同步模式”甚至是唯一的模式,因為執行環境是單執行緒的,如果允許同步執行所有http請求,伺服器效能會急劇下降,很快就會失去響應。本文總結了“非同步模式”程式設計的4種方法,理解它們可以讓你寫出結構更合理、效能更出色、維護更方便的Javascript程式。
一.回撥函式:
使用回撥函式是非同步程式設計的最基本的方法。
例如有兩個函式fun1和fun2,後者在等待前者的執行結果。
[JavaScript] 純文字檢視 複製程式碼fun1(); fun2();
如果fun1的執行時間很長,那麼就可以考慮把函式fun2作為fun1的回撥函式執行,將fun1改造如下:
[JavaScript] 純文字檢視 複製程式碼function fun1(callback){ setTimeout(function(){ // fun1的任務程式碼 callback(); }, 1000); }
於是程式碼執行就變成如下形式:
[JavaScript] 純文字檢視 複製程式碼fun1(fun2);
採用此種方式,就把同步操作變成了非同步操作,函式fun1並不能夠阻塞fun2的執行。
總結:回撥函式的優點是簡單、容易理解和部署,缺點是不利於程式碼的閱讀和維護,各個部分之間高度耦合(Coupling),流程會很混亂,而且每個任務只能指定一個回撥函式。
二.事件監聽:
採用事件驅動模式,這樣任務的執行不取決於程式碼的順序,而是取決於事件的發生順序。下面看程式碼解析:
為fun1繫結一個事件(採用jQuery方式):
[JavaScript] 純文字檢視 複製程式碼fun1.on(‘done’, fun2);
上面這行程式碼的意思是,當fun1發生done事件,就執行fun2。然後,對fun1進行改寫:
[JavaScript] 純文字檢視 複製程式碼function fun1(){ setTimeout(function () { // fun1的任務程式碼 fun1.trigger(‘done’); }, 1000); }
fun1.trigger(‘done’)表示,執行完成後,立即觸發done事件,從而開始執行fun2。
這種方法的優點是比較容易理解,可以繫結多個事件,每個事件可以指定多個回撥函式,而且可以“去耦合”(Decoupling),有利於實現模組化。缺點是整個程式都要變成事件驅動型,執行流程會變得很不清晰。
三.釋出/訂閱:
在第二種中的“事件”,完全可以理解為“訊號”。
假定,存在這樣的一個“訊號中心”,某個任務執行完成,就向訊號中心“釋出”(publish)一個訊號,其他任務可以向訊號中心“訂閱”(subscribe)這個訊號,從而知道什麼時候自己可以開始執行。這就叫做“釋出/訂閱模式”(publish-subscribe pattern),又稱“觀察者模式”(observer pattern)。
這個模式有多種實現,下面採用的是Ben Alman的Tiny Pub/Sub,這是jQuery的一個外掛。
首先,f2un向“訊號中心”jQuery訂閱“done”訊號。
[JavaScript] 純文字檢視 複製程式碼jQuery.subscribe(“done”, fun2)
然後,fun1進行如下改寫:
[JavaScript] 純文字檢視 複製程式碼function fun1(){ setTimeout(function () { // fun1的任務程式碼 jQuery.publish(“done”); }, 1000); }
jQuery.publish(“done”)的意思是,fun1執行完成後,向“訊號中心”jQuery釋出“done”訊號,從而引發fun2的執行。
此外,fun2完成執行後,也可以取消訂閱(unsubscribe)。
jQuery.unsubscribe(“done”, fun2);
這種方法的性質與“事件監聽”類似,但是明顯優於後者。因為我們可以通過檢視“訊息中心”,瞭解存在多少訊號、每個訊號有多少訂閱者,從而監控程式的執行。
四.Promises物件:
Promises物件是CommonJS工作組提出的一種規範,目的是為非同步程式設計提供統一介面。
簡單說,它的思想是,每一個非同步任務返回一個Promise物件,該物件有一個then方法,允許指定回撥函式。比如,fun1的回撥函式fun2,可以寫成:
[JavaScript] 純文字檢視 複製程式碼fun1().then(fun2);
fun1要進行如下改寫(這裡使用的是jQuery的實現):
[JavaScript] 純文字檢視 複製程式碼function f1(){ var dfd = $.Deferred(); setTimeout(function () { // f1的任務程式碼 dfd.resolve(); }, 500); return dfd.promise; }
這樣寫的優點在於,回撥函式變成了鏈式寫法,程式的流程可以看得很清楚,而且有一整套的配套方法,可以實現許多強大的功能。
比如,指定多個回撥函式:
[JavaScript] 純文字檢視 複製程式碼fun1().then(fun2).then(fun3);
再比如,指定發生錯誤時的回撥函式:
[JavaScript] 純文字檢視 複製程式碼fun1().then(fun2).fail(fun3);
相關文章
- JavaScript非同步程式設計的6種方法JavaScript非同步程式設計
- Javascript非同步程式設計的4種方法JavaScript非同步程式設計
- 幾種設計模式簡介(轉載)設計模式
- javascript 非同步程式設計的5種方式JavaScript非同步程式設計
- JavaScript非同步程式設計:非同步的資料收集方法JavaScript非同步程式設計
- JavaScript中的幾種資料結構簡介JavaScript資料結構
- JavaScript 模組化程式設計簡單介紹JavaScript程式設計
- Javascript 非同步程式設計JavaScript非同步程式設計
- JavaScript非同步程式設計JavaScript非同步程式設計
- JS非同步程式設計的幾種方式及區別JS非同步程式設計
- 非同步程式設計測試Awaitlity簡介| Baeldung非同步程式設計AI
- 23種設計模式簡介設計模式
- 探索Javascript非同步程式設計JavaScript非同步程式設計
- 三種Javascript(NodeJS)非同步程式設計程式碼模式比較JavaScriptNodeJS非同步程式設計模式
- Rust語言非同步程式設計簡介 - ShakaibRust非同步程式設計AI
- javascript物件導向程式設計概念簡單介紹JavaScript物件程式設計
- javascript函數語言程式設計簡單介紹JavaScript函數程式設計
- javascript如何實現模組程式設計簡單介紹JavaScript程式設計
- 你好,JavaScript非同步程式設計—- 理解JavaScript非同步的美妙JavaScript非同步程式設計
- 你好,JavaScript非同步程式設計---- 理解JavaScript非同步的美妙JavaScript非同步程式設計
- python 網路程式設計----非阻塞或非同步程式設計Python程式設計非同步
- [譯] 非同步程式設計:阻塞與非阻塞非同步程式設計
- 向非程式設計師解釋JavaScript程式設計師JavaScript
- 向非程式設計師解釋 JavaScript程式設計師JavaScript
- Javascript中的非同步程式設計JavaScript非同步程式設計
- JavaScript非同步程式設計筆記JavaScript非同步程式設計筆記
- 前端- JavaScript非同步程式設計Promise前端JavaScript非同步程式設計Promise
- Javascript非同步程式設計總結JavaScript非同步程式設計
- 談談 JavaScript 非同步程式設計JavaScript非同步程式設計
- JavaScript 非同步程式設計入門JavaScript非同步程式設計
- windows程式設計簡介Windows程式設計
- shell程式設計簡介程式設計
- javascript中常用的幾種彈出視窗簡單介紹JavaScript
- Socket程式設計中的同步、非同步、阻塞和非阻塞(轉)程式設計非同步
- IO程式設計和NIO程式設計簡介程式設計
- 幾種常用設計模式的簡單示例設計模式
- JavaScript非同步程式設計:Generator與AsyncJavaScript非同步程式設計
- JavaScript非同步程式設計-基礎篇JavaScript非同步程式設計