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