大家好,我是IT修真院深圳分院第02期學(xué)員,一枚正直善良的web程序員烟逊。
今天給大家分享一下,修真院官網(wǎng)js任務(wù)5踪栋,深度思考中的知識點——異步編程有哪幾種方法來實現(xiàn)?
1.背景介紹
Javascript語言的執(zhí)行環(huán)境是"單線程".所謂"單線程"焙格,就是指一次只能完成一件任務(wù)。如果有多個任務(wù)夷都,就必須排隊眷唉,前面一個任務(wù)完成,再執(zhí)行后面一個任務(wù)囤官,以此類推冬阳。
這種模式的好處是實現(xiàn)起來比較簡單,執(zhí)行環(huán)境相對單純党饮;壞處是只要有一個任務(wù)耗時很長肝陪,后面的任務(wù)都必須排隊等著,會拖延整個程序的執(zhí)行刑顺。常見的瀏覽器無響應(yīng)(假死)氯窍,往往就是因為某一段Javascript代碼長時間運行(比如死循環(huán))饲常,導(dǎo)致整個頁面卡在這個地方,其他任務(wù)無法執(zhí)行狼讨。
2.知識剖析
先了解下Javascript語言將任務(wù)的執(zhí)行模式贝淤。
Javascript語言將任務(wù)的執(zhí)行模式分成兩種:同步(Synchronous)和異步(Asynchronous)。
"同步模式":后一個任務(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ù)的排列順序是不一致的计济、異步的。非常重要排苍。在瀏覽器端沦寂,耗時很長的操作都應(yīng)該異步執(zhí)行,避免瀏覽器失去響應(yīng)淘衙,最好的例子就是Ajax操作传藏。在服務(wù)器端,"異步模式"甚至是唯一的模式彤守,因為執(zhí)行環(huán)境是單線程的毯侦,如果允許同步執(zhí)行所有http請求,服務(wù)器性能會急劇下降具垫,很快就會失去響應(yīng)侈离。
3.常見問題
有哪些方法實現(xiàn)"異步模式"編程?
4.解決方案
4.1.回調(diào)函數(shù):一般情況下,應(yīng)用程序時常通過API調(diào)用庫里所預(yù)先備好的函數(shù)筝蚕。但是有些庫函數(shù)卻要求應(yīng)用先傳給它一個函數(shù)卦碾,好在合適的時候調(diào)用,以完成目標(biāo)任務(wù)起宽。這個被傳入的洲胖、后又被調(diào)用的函數(shù)就稱為回調(diào)函數(shù)。
采用這種方式坯沪,我們把同步操作變成了異步操作绿映,f1不會堵塞程序運行,相當(dāng)于先執(zhí)行程序的主要邏輯腐晾,將耗時的操作推遲執(zhí)行叉弦。 回調(diào)函數(shù)的優(yōu)點是簡單丐一、容易理解和部署.
但是回調(diào)函數(shù)的方式存在如下的問題:
1.缺點是不利于代碼的閱讀和維護,各個部分之間高度耦合(Coupling)卸奉,流程會很混亂钝诚,而且每個任務(wù)只能指定一個回調(diào)函數(shù)。
2. 可能形成萬惡的嵌套金字塔榄棵,代碼不易閱讀;
3. 只能對應(yīng)一個回調(diào)函數(shù)潘拱,在很多場景中成為一個限制疹鳄。
4.2.事件監(jiān)聽:另一種思路是采用事件驅(qū)動模式。任務(wù)的執(zhí)行不取決于代碼的順序芦岂,而取決于某個事件是否發(fā)生瘪弓。
這種方法的優(yōu)點是比較容易理解,可以綁定多個事件禽最,每個事件可以指定多個回調(diào)函數(shù)腺怯,而且可以"去耦合"(Decoupling),有利于實現(xiàn)模塊化川无。缺點是整個程序都要變成事件驅(qū)動型呛占,運行流程會變得很不清晰。
4.3懦趋、發(fā)布/訂閱:我們假定晾虑,存在一個"信號中心",某個任務(wù)執(zhí)行完成仅叫,就向信號中心"發(fā)布"(publish)一個信號帜篇,其他任務(wù)可以向信號中心"訂閱"(subscribe)這個信號,從而知道什么時候自己可以開始執(zhí)行诫咱。這就叫做"發(fā)布/訂閱模式"(publish-subscribe pattern)笙隙,又稱"觀察者模式"(observer pattern)。這個模式有多種實現(xiàn)坎缭,下面采用的是Ben Alman的Tiny Pub/Sub竟痰,這是jQuery的一個插件。
首先幻锁,f2向"信號中心"jQuery訂閱"done"信號凯亮。
jQuery.publish("done")的意思是,f1執(zhí)行完成后哄尔,向"信號中心"jQuery發(fā)布"done"信號假消,從而引發(fā)f2的執(zhí)行。 此外岭接,f2完成執(zhí)行后富拗,也可以取消訂閱(unsubscribe)臼予。
這種方法的性質(zhì)與"事件監(jiān)聽"類似,但是明顯優(yōu)于后者啃沪。因為我們可以通過查看"消息中心"粘拾,了解存在多少信號、每個信號有多少訂閱者创千,從而監(jiān)控程序的運行缰雇。
4.4.Promise:Promise象征著一個異步操作的最終結(jié)果。Promises交互主要通過它的then方法追驴, then方法接受一個回調(diào)函數(shù)械哟,這個回調(diào)函數(shù)接受執(zhí)行成功的返回值或執(zhí)行失敗的錯誤原因, 錯誤原因一般是Error對象殿雪。Promises對象是CommonJS工作組提出的一種規(guī)范暇咆,目的是為異步編程提供統(tǒng)一接口。 簡單說丙曙,它的思想是爸业,每一個異步任務(wù)返回一個Promise對象,該對象有一個then方法亏镰,允許指定回調(diào)函數(shù)扯旷。
Promise有以下幾種狀態(tài):
1.pending: 初始狀態(tài), 既不是 fulfilled 也不是 rejected。
2.fulfilled: 表示操作被成功完成拆挥。
3.rejected: 表示該操作失敗薄霜。
而且,它還有一個前面三種方法都沒有的好處:如果一個任務(wù)已經(jīng)完成纸兔,再添加回調(diào)函數(shù)惰瓜,該回調(diào)函數(shù)會立即執(zhí)行。所以汉矿,你不用擔(dān)心是否錯過了某個事件或信號崎坊。這種方法的缺點就是編寫和理解,都相對比較難洲拇。
5.編碼實戰(zhàn)
6.擴展思考
promise中的互相鏈接的寫法
ES7的Async/Await
7.參考文獻
參考一:異步操作的幾種方法
參考二:ES7中的Async/Await
參考三:jq中的異步操作
8.視頻資料
今天的分享就到這里啦奈揍,歡迎大家點贊、轉(zhuǎn)發(fā)赋续、留言男翰、拍磚~
下期預(yù)告:angualr控制器是什么? 不見不散~