異步編程有哪幾種方法來實現(xiàn)?

大家好,我是IT修真院北京分院第22期的學(xué)員楊剛斑芜,一枚正直碗殷、純潔精绎、善良的前端程序員

今天給大家分享一下,修真院官網(wǎng)JS(職業(yè))任務(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.解決方案

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ù)。

function f() { ? ? ? ? ? ? ? ? ? ? ? ?function f1(callback) { ? ? ? ? ? ? ? ? ? ? ? ? ? ?setTimeout(function () { ? ? ? ? ? ? ? ? ? ? ? ? ? ?console.log('11111'); //f1的任務(wù)代碼 ? ? ? ? ? ? ? ? ? ? ? ? ? ?callback(); ? ? ? ? ? ? ? ? ? ? ? ? ? ?}, 1000); ? ? ? ? ? ? ? ? ? ? ? ?} ? ? ? ? ? ? ? ? ? ? ? ?f1(f2); ? ? ? ? ? ? ? ? ? ? ? ?function f2() { ? ? ? ? ? ? ? ? ? ? ? ? ? ?console.log('22222') ? ? ? ? ? ? ? ? ? ? ? ? ? ?} //這(f2)是回調(diào)函數(shù) ? ? ? ? ? ? ? ? ? ? ? ?function f3(){ ? ? ? ? ? ? ? ? ? ? ? ? ? ?console.log('33333') ? ? ? ? ? ? ? ? ? ? ? ?} ? ? ? ? ? ? ? ? ? ? ? ?f3() ? ? ? ? ? ? ? ? ? ? ? ?} ? ? ? ? ? ? ? ? ? ?f();

采用這種方式芹助,我們把同步操作變成了異步操作堂湖,f1不會堵塞程序運行,相當(dāng)于先執(zhí)行程序的主要邏輯状土,將耗時的操作推遲執(zhí)行无蜂。 回調(diào)函數(shù)的優(yōu)點是簡單、容易理解和部署.

但是回調(diào)函數(shù)的方式存在如下的問題

1.缺點是不利于代碼的閱讀和維護(hù)蒙谓,各個部分之間高度耦合(Coupling)斥季,流程會很混亂,而且每個任務(wù)只能指定一個回調(diào)函數(shù)累驮。

2. 可能形成萬惡的嵌套金字塔酣倾,代碼不易閱讀;

3. 只能對應(yīng)一個回調(diào)函數(shù)慰照,在很多場景中成為一個限制灶挟。

2.事件監(jiān)聽:另一種思路是采用事件驅(qū)動模式。任務(wù)的執(zhí)行不取決于代碼的順序毒租,而取決于某個事件是否發(fā)生稚铣。

//jQuery中 ? ? ? ? ? ? ? ? ? ?$("#p").on("click",function(){ ? ? ? ? ? ? ? ? ? ? ? ?alert("The paragraph was clicked."); ? ? ? ? ? ? ? ? ? ?}); ? ? ? ? ? ? ? ? ? ?//JavaScript中 ? ? ? ? ? ? ? ? ? ?document.getElementById("myBtn").addEventListener("click", displayDate); ? ? ? ? ? ? ? ? ? ?function displayDate() { ? ? ? ? ? ? ? ? ? ? ? ?document.getElementById("demo").innerHTML = Date(); ? ? ? ? ? ? ? ? ? ?}

這種方法的優(yōu)點是比較容易理解,可以綁定多個事件墅垮,每個事件可以指定多個回調(diào)函數(shù)惕医,而且可以"去耦合"(Decoupling),有利于實現(xiàn)模塊化算色。缺點是整個程序都要變成事件驅(qū)動型抬伺,運行流程會變得很不清晰。

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.subscribe("done", f2); ? ? ? ? ? ? ? ? function f1(){      ? ? ? ? ? ? ?setTimeout(function () {        ? ? ? ? ?// f1的任務(wù)代碼        ? ? ? ? ?jQuery.publish("done");      ? ? ? ? ? ? ?}, 1000);    ? ? ? ? ? ? ?} ? ? ? ? ? ? ? ? ?jQuery.unsubscribe("done", f2);

jQuery.publish("done")的意思是篷就,f1執(zhí)行完成后,向"信號中心"jQuery發(fā)布"done"信號阀溶,從而引發(fā)f2的執(zhí)行腻脏。 此外鸦泳,f2完成執(zhí)行后银锻,也可以取消訂閱(unsubscribe)。

這種方法的性質(zhì)與"事件監(jiān)聽"類似做鹰,但是明顯優(yōu)于后者击纬。因為我們可以通過查看"消息中心",了解存在多少信號钾麸、每個信號有多少訂閱者更振,從而監(jiān)控程序的運行。

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: 表示該操作失敗。

// 條件 ? ? ? ? ? ? ? ? ? ? var isOK=true; ? ? ? ? ? ? ? ? ? ?// Promise 函數(shù) ? ? ? ? ? ? ? ? ? ? ?//它的思想是赁还,每一個異步任務(wù)返回一個Promise對象妖泄,該對象有一個then方法 ? ? ? ? ? ? ? ? ? ? ? // 允許指定回調(diào)函數(shù)。 ? ? ? ? ? ? ? ? ? ?var payPhone= new Promise( ? ? ? ? ? ? ? ? ? ? ? ?function (resolve,reject) { ? ? ? ? ? ? ? ? ? ? ? ? ? ?// 條件為真 ? ? ? ? ? ? ? ? ? ? ? ? ? ?if (isOK) { ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?var phone={ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?brand:'iphone', ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?color:'black' ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?}; ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?resolve(phone); ? ? ? ? ? ? ? ? ? ? ? ? ? ?// 條件為假 ? ? ? ? ? ? ? ? ? ? ? ? ? ?} else{ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?var reason= new Error('不ok'); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?reject(reason) ? ? ? ? ? ? ? ? ? ? ? ? ? ?} ? ? ? ? ? ? ? ? ? ? ? ?}) ? ? ? ? ? ? ? ? ? ? var buy =function () { ? ? ? ? ? ? ? ? ? ? ? ?// 連綴寫法 ? ? ? ? ? ? ? ? ? ? ? ?payPhone ? ? ? ? ? ? ? ? ? ? ? ? .then(function (res) { ? ? ? ? ? ? ? ? ? ? ? ? ? ?console.log(res) ? ? ? ? ? ? ? ? ? ? ? ? }) ? ? ? ? ? ? ? ? ? ? ? ? .catch(function (error) { ? ? ? ? ? ? ? ? ? ? ? ? ? ?console.log(error) ? ? ? ? ? ? ? ? ? ? ? ? }) ? ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? ? buy()

而且秽浇,它還有一個前面三種方法都沒有的好處:如果一個任務(wù)已經(jīng)完成浮庐,再添加回調(diào)函數(shù),該回調(diào)函數(shù)會立即執(zhí)行。所以审残,你不用擔(dān)心是否錯過了某個事件或信號梭域。這種方法的缺點就是編寫和理解,都相對比較難搅轿。

5.編碼實戰(zhàn)

6.擴展思考

promise中的互相鏈接的寫法

ES7的Async/Await

異步函數(shù)的執(zhí)行順序病涨?

計時器可以異步計算計時器的時間,時間到了之后把函數(shù)加入到j(luò)s代碼隊列的最后璧坟,如果是間隔計時器既穆,js代碼堵塞時會在隊列末尾追加多次間隔計時器指定執(zhí)行的函數(shù),并會在執(zhí)行到他們的時候一下子全部執(zhí)行出來雀鹃,因為是等完間隔要執(zhí)行函數(shù)時才追加到的末尾幻工。

7.參考文獻(xiàn)

參考一:異步操作的幾種方法

參考二:ES7中的Async/Await

參考三:jq中的異步操作

參考三:jq中的異步操作

8.更多討論

q:jQ封裝了哪些異步操作?

A黎茎;1囊颅、jQuery $.ajax()

2、$.get 傅瞻、$.post等

Q:為什么要用ajax進(jìn)行異步操作踢代。

A:為了不阻塞程序運行,服務(wù)器端都是異步嗅骄,沒有同步操作胳挎,避免卡死

Q:能更好的解釋下毀掉函數(shù)嗎?

隨便寫個函數(shù)fun1和fun2溺森,fun1運行時慕爬,他在參數(shù)里面放入一個函數(shù)fun2作為他的回調(diào)函數(shù)callback,在fun1執(zhí)行的最后儿惫,執(zhí)行callback()也就是fun2函數(shù)澡罚,這樣就完成了一個回調(diào)函數(shù)。它的目的是讓fun2放在fun1的后面執(zhí)行肾请,同時也不會因為要執(zhí)行fun2而阻塞運行留搔。

著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán)铛铁,非商業(yè)轉(zhuǎn)載請注明出處隔显。

視頻鏈接:

https://pan.baidu.com/s/1boT8UPT?密碼:?4r93

ppt鏈接:https://ptteng.github.io/PPT/PPT/JS-05-async.html#/

今天的分享就到這里啦,歡迎大家點贊饵逐、轉(zhuǎn)發(fā)括眠、留言、拍磚~

------------------------------------------------------------------------------------------------------------------------

技能樹.IT修真院

“我們相信人人都可以成為一個工程師倍权,現(xiàn)在開始掷豺,找個師兄捞烟,帶你入門,掌控自己學(xué)習(xí)的節(jié)奏当船,學(xué)習(xí)的路上不再迷锰饣”。

這里是技能樹.IT修真院德频,成千上萬的師兄在這里找到了自己的學(xué)習(xí)路線苍息,學(xué)習(xí)透明化,成長可見化壹置,師兄1對1免費指導(dǎo)竞思。快來與我一起學(xué)習(xí)吧?钞护!

猛戳這里

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末盖喷,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子患亿,更是在濱河造成了極大的恐慌传蹈,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件步藕,死亡現(xiàn)場離奇詭異,居然都是意外死亡挑格,警方通過查閱死者的電腦和手機咙冗,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來漂彤,“玉大人雾消,你說我怎么就攤上這事〈焱” “怎么了立润?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長媳板。 經(jīng)常有香客問我桑腮,道長,這世上最難降的妖魔是什么蛉幸? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任破讨,我火速辦了婚禮,結(jié)果婚禮上奕纫,老公的妹妹穿的比我還像新娘提陶。我一直安慰自己,他們只是感情好匹层,可當(dāng)我...
    茶點故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布隙笆。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪撑柔。 梳的紋絲不亂的頭發(fā)上煤率,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天,我揣著相機與錄音乏冀,去河邊找鬼蝶糯。 笑死,一個胖子當(dāng)著我的面吹牛辆沦,可吹牛的內(nèi)容都是我干的昼捍。 我是一名探鬼主播,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼肢扯,長吁一口氣:“原來是場噩夢啊……” “哼妒茬!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起蔚晨,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤乍钻,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后铭腕,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體银择,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年累舷,在試婚紗的時候發(fā)現(xiàn)自己被綠了浩考。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡被盈,死狀恐怖析孽,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情只怎,我是刑警寧澤袜瞬,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站身堡,受9級特大地震影響邓尤,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜盾沫,卻給世界環(huán)境...
    茶點故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一裁赠、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧赴精,春花似錦佩捞、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽莲蜘。三九已至,卻和暖如春帘营,著一層夾襖步出監(jiān)牢的瞬間票渠,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工芬迄, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留问顷,地道東北人。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓禀梳,卻偏偏與公主長得像杜窄,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子算途,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,713評論 2 354

推薦閱讀更多精彩內(nèi)容