摘要:對于而言,異步編程我們可以采用回調函數,事件監聽,發布訂閱等方案,在之后,又新添了,,的方案。總結本文闡述了從回調函數到的演變歷史。參考文檔深入掌握異步編程系列理解的
對于JS而言,異步編程我們可以采用回調函數,事件監聽,發布訂閱等方案,在ES6之后,又新添了Promise,Genertor,Async/Await的方案。本文將闡述從回調函數到Async/Await的演變歷史,以及它們之間的關系。1. 異步編程的演變
首先假設要渲染一個頁面,只能異步的串行請求A,B,C,然后才能拿到頁面的數據并請求頁面
針對于不同的異步編程方式,我們會得到如下的代碼:
1.1 回調函數// 假設request是一個異步函數 request(A, function () { request(B, function () { request(C, function () { // 渲染頁面 }) }) })
回調函數的嵌套是愈發深入的。在不斷的回調中,request(A)回調函數中的其他邏輯會影響到request(B),request(C)中的邏輯,同理,request(B)中的其他邏輯也會影響到request(C)。在這個例子中,request(A)調用request(B),request(B)調用request(C),request(C)執行完畢返回,request(B)執行完畢返回,request(A)執行完畢返回。我們很快會對先后順序產生混亂,從而很難直觀的分析出異步回調的結果。這就被稱為回調地獄。
為了解決這種情況,ES6新增了Promise對象。
1.2 Promise// 假設request是一個Promise函數 request(A).then(function () { return request(B) }).then(function () { return request(C) }).then(function () { // 渲染頁面 })
Promise對象用then函數來指定回調。所以,之前在1.1中回調函數的例子可以改為上文中的模樣。可以看到,Promise并沒有消除回調地獄,但是卻通過then鏈將代碼邏輯變得更加清晰了。在這個例子中,request(A)調用request(B),request(B)調用request(C),request(C)執行完畢返回。現在,request(A)中的內容只能通過顯示聲明的data來影響到request(C)——如果沒有顯示的在回調中聲明,則影響不了request(C),換言之,每段回調被近乎獨立的分割了。
但是Promise本身還是有一堆的then,還是不能讓我們像寫同步代碼一樣寫異步的代碼,因此JS又引入了Generator。
1.3 Generatorfunction* gen(){ var r1 = yield request(A) var r2 = yield request(B) var r3 = yield request(C) // 渲染頁面 };
Generator是協程在ES6上的實現,協程是指一個線程上不同函數間執行權可以相互切換。如本例,先執行gen(),然后在遇到yield時暫停,執行權交給request(A),等到調用了next()方法,再將執行權還給gen()。
通過協程,JS就實現了用同步的方式寫異步的代碼,但是Generator的使用要配合執行器,這自然是麻煩的。于是就有了Async/Await。
Generator的自動執行器是co函數庫,有興趣的同學可以通過閱讀《co 函數庫的含義和用法》來進行了解。1.4 Async/Await
async function gen() { var r1 = await request(A) var r2 = await request(B) var r3 = await request(C) // 渲染頁面 }
如果比較代碼的話,1.4的代碼只是把1.3的代碼中* => async,yield變為await。但Async函數的實現,就是將 Generator函數和自動執行器,包裝在一個函數里[1]。spawn就是自動執行器。
async function fn(args){ // ... } // 等同于 function fn(args){ return spawn(function*() { // ... }); }
除此以外,Async函數比Generator函數有更好的延展性——yield接的是Promise函數/Thunk函數,但await還可以包括普通函數。對于普通函數,await表達式的運算結果就是它等到的東西。否則若await等到的是一個Promise函數,await就會協程到這個Promise函數上,直到它resolve或者reject,然后再協程回主函數上[2]。當然,Async函數也比Generator函數更加易讀和易理解。
2. 總結本文闡述了從回調函數到Async/Await的演變歷史。Async函數作為換一個終極解決方案,盡管在并行異步處理上還要借助Promise.all(),但其他方面已經足夠完美。
參考文檔《深入掌握 ECMAScript 6 異步編程》系列
《理解JavaScript的 async/await》
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/108887.html
摘要:三即生成器,它是生成器函數返回的一個對象,是中提供的一種異步編程解決方案而生成器函數有兩個特征,一是函數名前帶星號,二是內部執行語句前有關鍵字調用一個生成器函數并不會馬上執行它里面的語句,而是返回一個這個生成器的迭代器對象。 文章來自微信公眾號:前端工坊(fe_workshop),不定期更新有趣、好玩的前端相關原創技術文章。 如果喜歡,請關注公眾號:前端工坊版權歸微信公眾號所有,轉載請...
摘要:的翻譯文檔由的維護很多人說,阮老師已經有一本關于的書了入門,覺得看看這本書就足夠了。前端的異步解決方案之和異步編程模式在前端開發過程中,顯得越來越重要。為了讓編程更美好,我們就需要引入來降低異步編程的復雜性。 JavaScript Promise 迷你書(中文版) 超詳細介紹promise的gitbook,看完再不會promise...... 本書的目的是以目前還在制定中的ECMASc...
摘要:從最開始的到封裝后的都在試圖解決異步編程過程中的問題。為了讓編程更美好,我們就需要引入來降低異步編程的復雜性。異步編程入門的全稱是前端經典面試題從輸入到頁面加載發生了什么這是一篇開發的科普類文章,涉及到優化等多個方面。 TypeScript 入門教程 從 JavaScript 程序員的角度總結思考,循序漸進的理解 TypeScript。 網絡基礎知識之 HTTP 協議 詳細介紹 HTT...
摘要:從最開始的到封裝后的都在試圖解決異步編程過程中的問題。為了讓編程更美好,我們就需要引入來降低異步編程的復雜性。寫一個符合規范并可配合使用的寫一個符合規范并可配合使用的理解的工作原理采用回調函數來處理異步編程。 JavaScript怎么使用循環代替(異步)遞歸 問題描述 在開發過程中,遇到一個需求:在系統初始化時通過http獲取一個第三方服務器端的列表,第三方服務器提供了一個接口,可通過...
閱讀 1554·2021-11-19 09:55
閱讀 2778·2021-09-06 15:02
閱讀 3534·2019-08-30 15:53
閱讀 1071·2019-08-29 16:36
閱讀 1230·2019-08-29 16:29
閱讀 2286·2019-08-29 15:21
閱讀 621·2019-08-29 13:45
閱讀 2679·2019-08-26 17:15