異步操作

1.單線程模型

單線程模型指的是驹暑,JavaScript 只在一個線程上運行拨脉。也就是說或衡,JavaScript 同時只能執(zhí)行一個任務(wù)焦影,其他任務(wù)都必須在后面排隊等待。

注意封断,JavaScript 只在一個線程上運行斯辰,不代表 JavaScript 引擎只有一個線程。事實上坡疼,JavaScript 引擎有多個線程彬呻,單個腳本只能在一個線程上運行(稱為主線程),其他線程都是在后臺配合。

JavaScript 之所以采用單線程闸氮,而不是多線程剪况,跟歷史有關(guān)系。JavaScript 從誕生起就是單線程蒲跨,原因是不想讓瀏覽器變得太復雜译断,因為多線程需要共享資源、且有可能修改彼此的運行結(jié)果或悲,對于一種網(wǎng)頁腳本語言來說孙咪,這就太復雜了。如果 JavaScript 同時有兩個線程巡语,一個線程在網(wǎng)頁 DOM 節(jié)點上添加內(nèi)容翎蹈,另一個線程刪除了這個節(jié)點,這時瀏覽器應該以哪個線程為準男公?是不是還要有鎖機制荤堪?所以,為了避免復雜性枢赔,JavaScript 一開始就是單線程澄阳,這已經(jīng)成了這門語言的核心特征,將來也不會改變糠爬。

這種模式的好處是實現(xiàn)起來比較簡單寇荧,執(zhí)行環(huán)境相對單純举庶;壞處是只要有一個任務(wù)耗時很長执隧,后面的任務(wù)都必須排隊等著,會拖延整個程序的執(zhí)行户侥。常見的瀏覽器無響應(假死)镀琉,往往就是因為某一段 JavaScript 代碼長時間運行(比如死循環(huán)),導致整個頁面卡在這個地方蕊唐,其他任務(wù)無法執(zhí)行屋摔。JavaScript 語言本身并不慢,慢的是讀寫外部數(shù)據(jù)替梨,比如等待 Ajax 請求返回結(jié)果钓试。這個時候,如果對方服務(wù)器遲遲沒有響應副瀑,或者網(wǎng)絡(luò)不通暢弓熏,就會導致腳本的長時間停滯。

如果排隊是因為計算量大糠睡,CPU 忙不過來挽鞠,倒也算了,但是很多時候 CPU 是閑著的,因為 IO 操作(輸入輸出)很慢(比如 Ajax 操作從網(wǎng)絡(luò)讀取數(shù)據(jù))信认,不得不等著結(jié)果出來材义,再往下執(zhí)行。JavaScript 語言的設(shè)計者意識到嫁赏,這時 CPU 完全可以不管 IO 操作其掂,掛起處于等待中的任務(wù),先運行排在后面的任務(wù)橄教。等到 IO 操作返回了結(jié)果清寇,再回過頭,把掛起的任務(wù)繼續(xù)執(zhí)行下去护蝶。這種機制就是 JavaScript 內(nèi)部采用的“事件循環(huán)”機制(Event Loop)华烟。

單線程模型雖然對 JavaScript 構(gòu)成了很大的限制,但也因此使它具備了其他語言不具備的優(yōu)勢持灰。如果用得好盔夜,JavaScript 程序是不會出現(xiàn)堵塞的,這就是為什么 Node 可以用很少的資源堤魁,應付大流量訪問的原因喂链。

為了利用多核 CPU 的計算能力,HTML5 提出 Web Worker 標準妥泉,允許 JavaScript 腳本創(chuàng)建多個線程椭微,但是子線程完全受主線程控制,且不得操作 DOM盲链。所以蝇率,這個新標準并沒有改變 JavaScript 單線程的本質(zhì)。

2.同步任務(wù)和異步任務(wù)

程序里面所有的任務(wù)刽沾,可以分成兩類:同步任務(wù)(synchronous)和異步任務(wù)(asynchronous)本慕。

同步任務(wù)是那些沒有被引擎掛起、在主線程上排隊執(zhí)行的任務(wù)侧漓。只有前一個任務(wù)執(zhí)行完畢锅尘,才能執(zhí)行后一個任務(wù)。

異步任務(wù)是那些被引擎放在一邊布蔗,不進入主線程藤违、而進入任務(wù)隊列的任務(wù)。只有引擎認為某個異步任務(wù)可以執(zhí)行了(比如 Ajax 操作從服務(wù)器得到了結(jié)果)纵揍,該任務(wù)(采用回調(diào)函數(shù)的形式)才會進入主線程執(zhí)行顿乒。排在異步任務(wù)后面的代碼,不用等待異步任務(wù)結(jié)束會馬上運行骡男,也就是說淆游,異步任務(wù)不具有“堵塞”效應傍睹。

舉例來說,Ajax 操作可以當作同步任務(wù)處理犹菱,也可以當作異步任務(wù)處理拾稳,由開發(fā)者決定。如果是同步任務(wù)腊脱,主線程就等著 Ajax 操作返回結(jié)果访得,再往下執(zhí)行;如果是異步任務(wù)陕凹,主線程在發(fā)出 Ajax 請求以后悍抑,就直接往下執(zhí)行,等到 Ajax 操作有了結(jié)果杜耙,主線程再執(zhí)行對應的回調(diào)函數(shù)搜骡。

3.任務(wù)隊列和事件循環(huán)

JavaScript 運行時,除了一個正在運行的主線程佑女,引擎還提供一個任務(wù)隊列(task queue)记靡,里面是各種需要當前程序處理的異步任務(wù)。(實際上团驱,根據(jù)異步任務(wù)的類型摸吠,存在多個任務(wù)隊列。為了方便理解嚎花,這里假設(shè)只存在一個隊列寸痢。)

首先,主線程會去執(zhí)行所有的同步任務(wù)紊选。等到同步任務(wù)全部執(zhí)行完啼止,就會去看任務(wù)隊列里面的異步任務(wù)。如果滿足條件丛楚,那么異步任務(wù)就重新進入主線程開始執(zhí)行族壳,這時它就變成同步任務(wù)了憔辫。等到執(zhí)行完趣些,下一個異步任務(wù)再進入主線程開始執(zhí)行。一旦任務(wù)隊列清空贰您,程序就結(jié)束執(zhí)行坏平。

異步任務(wù)的寫法通常是回調(diào)函數(shù)。一旦異步任務(wù)重新進入主線程锦亦,就會執(zhí)行對應的回調(diào)函數(shù)舶替。如果一個異步任務(wù)沒有回調(diào)函數(shù),就不會進入任務(wù)隊列杠园,也就是說顾瞪,不會重新進入主線程,因為沒有用回調(diào)函數(shù)指定下一步的操作。

JavaScript 引擎怎么知道異步任務(wù)有沒有結(jié)果陈醒,能不能進入主線程呢惕橙?答案就是引擎在不停地檢查,一遍又一遍钉跷,只要同步任務(wù)執(zhí)行完了弥鹦,引擎就會去檢查那些掛起來的異步任務(wù),是不是可以進入主線程了爷辙。這種循環(huán)檢查的機制彬坏,就叫做事件循環(huán)(Event Loop)。維基百科的定義是:“事件循環(huán)是一個程序結(jié)構(gòu)膝晾,用于等待和發(fā)送消息和事件(a programming construct that waits for and dispatches events or messages in a program)”栓始。

來源:JavaScript 標準參考教程

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市血当,隨后出現(xiàn)的幾起案子混滔,更是在濱河造成了極大的恐慌,老刑警劉巖歹颓,帶你破解...
    沈念sama閱讀 217,907評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件坯屿,死亡現(xiàn)場離奇詭異,居然都是意外死亡巍扛,警方通過查閱死者的電腦和手機领跛,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,987評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來撤奸,“玉大人吠昭,你說我怎么就攤上這事‰使希” “怎么了矢棚?”我有些...
    開封第一講書人閱讀 164,298評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長府喳。 經(jīng)常有香客問我蒲肋,道長,這世上最難降的妖魔是什么钝满? 我笑而不...
    開封第一講書人閱讀 58,586評論 1 293
  • 正文 為了忘掉前任兜粘,我火速辦了婚禮,結(jié)果婚禮上弯蚜,老公的妹妹穿的比我還像新娘孔轴。我一直安慰自己,他們只是感情好碎捺,可當我...
    茶點故事閱讀 67,633評論 6 392
  • 文/花漫 我一把揭開白布路鹰。 她就那樣靜靜地躺著贷洲,像睡著了一般。 火紅的嫁衣襯著肌膚如雪晋柱。 梳的紋絲不亂的頭發(fā)上恩脂,一...
    開封第一講書人閱讀 51,488評論 1 302
  • 那天,我揣著相機與錄音趣斤,去河邊找鬼俩块。 笑死,一個胖子當著我的面吹牛浓领,可吹牛的內(nèi)容都是我干的玉凯。 我是一名探鬼主播,決...
    沈念sama閱讀 40,275評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼联贩,長吁一口氣:“原來是場噩夢啊……” “哼漫仆!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起泪幌,我...
    開封第一講書人閱讀 39,176評論 0 276
  • 序言:老撾萬榮一對情侶失蹤盲厌,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后祸泪,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體吗浩,經(jīng)...
    沈念sama閱讀 45,619評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,819評論 3 336
  • 正文 我和宋清朗相戀三年没隘,在試婚紗的時候發(fā)現(xiàn)自己被綠了懂扼。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,932評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡右蒲,死狀恐怖阀湿,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情瑰妄,我是刑警寧澤陷嘴,帶...
    沈念sama閱讀 35,655評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站间坐,受9級特大地震影響灾挨,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜眶诈,卻給世界環(huán)境...
    茶點故事閱讀 41,265評論 3 329
  • 文/蒙蒙 一涨醋、第九天 我趴在偏房一處隱蔽的房頂上張望瓜饥。 院中可真熱鬧逝撬,春花似錦、人聲如沸乓土。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,871評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至狡相,卻和暖如春梯轻,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背尽棕。 一陣腳步聲響...
    開封第一講書人閱讀 32,994評論 1 269
  • 我被黑心中介騙來泰國打工喳挑, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人滔悉。 一個月前我還...
    沈念sama閱讀 48,095評論 3 370
  • 正文 我出身青樓伊诵,卻偏偏與公主長得像,于是被迫代替她去往敵國和親回官。 傳聞我的和親對象是個殘疾皇子曹宴,可洞房花燭夜當晚...
    茶點故事閱讀 44,884評論 2 354

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

  • 單線程模型 單線程模型指的是,JavaScript 只在一個線程上運行歉提。也就是說笛坦,JavaScript 同時只能執(zhí)...
    oWSQo閱讀 215評論 0 1
  • 1.單線程模型 單線程模型指JavaScript只在一個線程上運行。即苔巨,JS同時只能執(zhí)行一個任務(wù)版扩,其它任務(wù)都必須在...
    未vv閱讀 380評論 0 0
  • 一舷胜、單線程 主線程:JavaScript是單線程的娩践,所謂單線程,是指在JS引擎中負責解釋和執(zhí)行JavaScript...
    puxiaotaoc閱讀 21,036評論 7 32
  • JavaScript只在一個線程上運行烹骨。也就是說JavaScript同時只能執(zhí)行一個任務(wù)翻伺,其他的任務(wù)都必須在后面排...
    wxyzcctn閱讀 2,713評論 0 3
  • 1.背景介紹 同步指的是一次只能完成一件任務(wù)。如果有多個任務(wù)沮焕,就必須排隊吨岭,前面一個任務(wù)完成,再執(zhí)行后面一個任務(wù)峦树,以...
    inspg閱讀 4,891評論 0 6