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