摘要:以下總結了異步編程的種方式回調函數回調函數異步編程的最基本的方式。由小組的成員在規范中提出,目的是為異步編程提供統一接口。結尾參考文章異步編程參考文章使用詳解
前言
Javascript語言的執行環境是“單線程”。
單線程: 一次只能完成一個任務。如果有多個任務,就必須排隊,前面一個任務完成,再執行后面一個任務。
單線程的好處是執行環境簡單,壞處是在一些耗時的任務上會堵塞進程。比如讀取一個大文件,線程卡在這個任務上,造成頁面卡死。
那如何在讀取文件的同時,又能查看圖片,做一些其他的事呢?
這就到了“同步”和“異步”之爭:
同步:后一個任務等待前一個任務結束,然后再執行,程序的執行順序與任務的排列順序是一致的、同步的。
異步:每一個任務有一個或多個回調函數(callback),前一個任務結束后,不是執行后一個任務,而是執行回調函數,后一個任務則是不等前一個任務結束就執行,所以程序的執行順序與任務的排列順序是不一致的、異步的。
舉個栗子:
去餐廳吃飯
同步:大家依次排隊,前一個人付完錢,等待領取食物。。。漫長等待。。。食物做好了,后一個人跟進。
異步:大家依次排隊,前一個人付完錢,服務員給他一個餐牌,后一個人跟進。餐牌對應的食物做好了,再去領取。
以下總結了“異步編程”的4種方式:
1. 回調函數回調函數:異步編程的最基本的方式。
下面通過樣例作為演示:我們定義三個方法“做飯”(cook)、“吃飯”(eat),“洗碗”(wash)三個方法,它們是層層依賴的關系,下一步的的操作需要使用上一部操作的結果(這里使用 setTimeout 模擬異步操作)。
// 做飯 function cook() { console.log("開始做飯..."); sleep(2000); // 等待2秒 console.log("做飯完畢"); } // 吃飯 function eat() { console.log("開始吃飯..."); sleep(2000); // 等待2秒 console.log("吃飯完畢"); } // 洗碗 function wash() { console.log("開始洗碗..."); sleep(2000); // 等待2秒 console.log("洗碗完畢"); } // 阻塞等待(毫秒) function sleep(delay) { let start = (new Date()).getTime(); while((new Date()).getTime() - start < delay) { continue; } } cook(); eat(); wash(); // 開始做飯... // 做飯完畢 // 開始吃飯... // 吃飯完畢 // 開始洗碗... // 洗碗完畢
上面是“同步”的寫法,下面我們改寫成“異步”:回調函數
// 做飯 function cook(callback) { console.log("開始做飯..."); setTimeout(function() { console.log("做飯完畢"); // 這里是回調,執行吃飯的方法 callback(); }, 2000); } // 吃飯 function eat(callback) { console.log("開始吃飯..."); setTimeout(function() { console.log("吃飯完畢"); // 這里是回調,執行洗碗的方法 callback(); }, 2000); } // 洗碗 function wash() { console.log("開始洗碗..."); setTimeout(function() { console.log("洗碗完畢"); // 洗碗之后的其他動作,這里就不寫了 }, 2000); } cook(function() { eat(function() { wash(); }) }); // 開始做飯... // 做飯完畢 // 開始吃飯... // 吃飯完畢 // 開始洗碗... // 洗碗完畢
回調函數的優點是簡單、容易理解和部署,缺點是不利于代碼的閱讀和維護,各個部分之間高度耦合(Coupling),流程會很混亂,而且每個任務只能指定一個回調函數。
2. 事件監聽事件監聽:采用事件驅動模式,任務的執行不取決于代碼的順序,而取決于某個事件是否發生。
let events = require("events"); let eventEmitter = new events.EventEmitter(); // 做飯 var cook = function() { console.log("開始做飯..."); setTimeout(function() { console.log("做飯完畢"); // 執行eat事件 eventEmitter.emit("eatEvent"); }, 2000); } // 吃飯 var eat = function() { console.log("開始吃飯..."); setTimeout(function() { console.log("吃飯完畢"); // 執行wash事件 eventEmitter.emit("washEvent"); }, 2000); } // 洗碗 var wash = function() { console.log("開始洗碗..."); setTimeout(function() { console.log("洗碗完畢"); // 洗碗之后的其他動作,這里就不寫了 }, 2000); } // 綁定cook事件 eventEmitter.on("cookEvent", cook); // 綁定eat事件 eventEmitter.on("eatEvent", eat); // 綁定wash事件 eventEmitter.on("washEvent", wash); // 執行cook事件 eventEmitter.emit("cookEvent"); // 開始做飯... // 做飯完畢 // 開始吃飯... // 吃飯完畢 // 開始洗碗... // 洗碗完畢
這種方法的優點是比較容易理解,可以綁定多個事件,每個事件可以指定多個回調函數,而且可以"去耦合"(Decoupling),有利于實現模塊化。缺點是整個程序都要變成事件驅動型,運行流程會變得很不清晰
3. 發布/訂閱發布/訂閱:又稱“觀察者模式”。我們假定,存在一個"信號中心",某個任務執行完成,就向信號中心"發布"(publish)一個信號,其他任務可以向信號中心"訂閱"(subscribe)這個信號,從而知道什么時候自己可以開始執行。
和上一個“事件監聽”很類似,本人對這種模式理解有限,這里就不列代碼誤導大家了。
4. PromisePromise: 由 CommonJS 小組的成員在 Promise/A 規范中提出,目的是為異步編程提供統一接口。
根據 Promise/A 規范,promise 是一個對象,只需要 then 這一個方法。
// 做飯 function cook() { console.log("開始做飯..."); let promise = new Promise(function(resolve, reject) { setTimeout(function() { console.log("做飯完畢"); resolve(); }, 2000); }); return promise; } // 吃飯 function eat(callback) { console.log("開始吃飯..."); let promise = new Promise(function(resolve, reject) { setTimeout(function() { console.log("吃飯完畢"); resolve(); }, 2000); }); return promise; } // 洗碗 function wash() { console.log("開始洗碗..."); let promise = new Promise(function(resolve, reject) { setTimeout(function() { console.log("洗碗完畢"); // 洗碗之后的其他動作,這里就不寫了 resolve(); }, 2000); }); return promise; } cook() .then(function() { return eat(); }) .then(function() { return wash(); }) .then(function() { console.log("結束..."); }) .catch(function() { console.log("好像出什么問題了"); });
優點:
回調函數變成了鏈式寫法,程序的流程可以看得很清楚,而且有一整套的配套方法,可以實現許多強大的功能。解決回調地獄(Callback Hell)問題
更好地進行錯誤捕獲
Promise的功能不僅僅只上面用到的,諸如其他all(), race()之類,限于篇幅,大家可以翻看其他文章查看。
結尾參考文章:Javascript異步編程
參考文章:Promise使用詳解
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/102916.html
摘要:的翻譯文檔由的維護很多人說,阮老師已經有一本關于的書了入門,覺得看看這本書就足夠了。前端的異步解決方案之和異步編程模式在前端開發過程中,顯得越來越重要。為了讓編程更美好,我們就需要引入來降低異步編程的復雜性。 JavaScript Promise 迷你書(中文版) 超詳細介紹promise的gitbook,看完再不會promise...... 本書的目的是以目前還在制定中的ECMASc...
摘要:與異步編程按照維基百科上的解釋獨立于主控制流之外發生的事件就叫做異步。因為的存在,至少在被標準化的那一刻起,就支持異步編程了。然而異步編程真正發展壯大,的流行功不可沒。在握手過程中,端點交換認證和密鑰以建立或恢復安全會話。 1、前端 排序算法總結 排序算法可能是你學編程第一個學習的算法,還記得冒泡嗎? 當然,排序和查找兩類算法是面試的熱門選項。如果你是一個會寫快排的程序猿,面試官在比較...
摘要:與異步編程按照維基百科上的解釋獨立于主控制流之外發生的事件就叫做異步。因為的存在,至少在被標準化的那一刻起,就支持異步編程了。然而異步編程真正發展壯大,的流行功不可沒。在握手過程中,端點交換認證和密鑰以建立或恢復安全會話。 1、前端 排序算法總結 排序算法可能是你學編程第一個學習的算法,還記得冒泡嗎? 當然,排序和查找兩類算法是面試的熱門選項。如果你是一個會寫快排的程序猿,面試官在比較...
摘要:與異步編程按照維基百科上的解釋獨立于主控制流之外發生的事件就叫做異步。因為的存在,至少在被標準化的那一刻起,就支持異步編程了。然而異步編程真正發展壯大,的流行功不可沒。在握手過程中,端點交換認證和密鑰以建立或恢復安全會話。 1、前端 排序算法總結 排序算法可能是你學編程第一個學習的算法,還記得冒泡嗎? 當然,排序和查找兩類算法是面試的熱門選項。如果你是一個會寫快排的程序猿,面試官在比較...
摘要:異步規定要做一件事,不是立馬執行這件事,需要等一定的時間,這樣的話,我們不會等著它執行,而是繼續執行下面的操作,只有將下面的事情處理完了,才會返回頭處理之前的事情如果下面的事情并沒有處理完成,不管之前的事情有沒有到時間,都踏踏實實的給我等著 異步:規定要做一件事,不是立馬執行這件事,需要等一定的時間,這樣的話,我們不會等著它執行,而是繼續執行下面的操作,只有將下面的事情處理完了,才會返...
閱讀 2137·2023-04-26 00:23
閱讀 807·2021-09-08 09:45
閱讀 2435·2019-08-28 18:20
閱讀 2542·2019-08-26 13:51
閱讀 1595·2019-08-26 10:32
閱讀 1392·2019-08-26 10:24
閱讀 2027·2019-08-26 10:23
閱讀 2196·2019-08-23 18:10