基於瀏覽器的事件輪詢機制(以及Node.js中的事件輪詢機制),JavaScript常常會運作在非同步環境中。由於JavaScript本身語言的特性(不需要程式設計師操控執行緒/進程),在js中解決非同步化程式設計的方法就顯得相當重要。可以說一個完整的專案中,js開發人員是不可能不面對非同步操作的。
一.回呼函數
(1)經典回呼函數方式:巢狀內聯函數
#假設我們有一個ajax()方法,他接收一個url參數,向該位址發起一個非同步請求,在請求結束時執行第二個參數—一個回呼函數:
ajax(url,function(result){ console.log(result); });
可以說這種方式幾乎是每個前端開發人員都用過的回調函數方式,有了這樣的回調機制,開發人員就不用編寫類似下面這樣的程式碼來推測伺服器請求什麼時候返回:
var result=ajax(url); setTimeout(function(result){ console.log(result); },400);
大家應該可以明白我這裡想表達的意思。我們設定了一個延遲400毫秒的計時器,來假設我們發出的ajax請求會在400毫秒之內完成。否則,我們將會操作一個undefined的result。
但有一個問題隨著專案的擴大漸漸浮現出來:如果場景需要我們多層嵌套回呼函數,程式碼將變得難以閱讀和維護:
ajax(url0,function(result0){ ajax(result0.url1,function(result1){ ajax(result1.url2,function(result2){ console.log(result2); }); }); });
(2)呼叫外部函數
為了解決內聯回呼函數暴露出來的程式碼混亂問題,我們引入外部函數呼叫來解決類似問題:
function handle2(result){ console.log(result); } function handle1(result){ ajax(result.url,function(result){ handle2(result); }); } ajax(url,function(result){ handle1(result); });
透過這個拆分內聯函數,來呼叫外部函數的最佳化方法,能極大的保持程式碼的簡潔性。
二.制定回呼管理器
觀察流行的JavaScript流程控制工具,例如Nimble、Step、Seq,我們會學習到一個簡潔的設計模式:透過回呼管理器來控制非同步JavaScript執行流程,以下是一個典型的回呼管理器的關鍵程式碼範例:
var Flow={}; //设置next方法,在上一个方法完成时调用下一个方法 Flow.next=function(){ if(this.stack[0]){ //弹出方法栈中的第一个方法,并执行他 this.stack.shift()(); } }; //设置series方法,接收一个函数数组,并按序执行 Flow.series=function(arr){ this.stack=arr; this.next(); }; //通过Flow.series我们能够控制传入的函数的执行顺序 Flow.series([ function(){ //do something console.log(1); Flow.next(); }, function(next){ //do something console.log(2); Flow.next(); } ]);
我們初始化了一個Flow控制器,為他設計了series和next兩個函數屬性。在我們編寫的業務方法內部,在方法結尾處透過呼叫Flow.next()的方式來順序觸發下一個方法;透過執行series方法來順序執行非同步函數。這種透過核心控制器來管理非同步函數呼叫的方式簡化了我們的程式設計過程,讓開發人員能夠投入更多精力在業務邏輯上。
以上是javascript非同步程式設計之回呼函數與管理器用法實例詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!