jquery的同步和異步底層機制詳解

????????都知道JavaScript是單線程語言,而單線程的設定其實與它的用途有關缭黔。作為瀏覽器腳本語言,JavaScript的主要用途是與用戶互動蒂破,以及操作DOM馏谨。這決定了它只能是單線程,否則會帶來很復雜的同步問題附迷。比如惧互,假定JavaScript同時有兩個線程,一個線程在某個DOM節(jié)點上添加內容喇伯,另一個線程刪除了這個節(jié)點喊儡,這時瀏覽器應該以哪個線程為準?

????????所以稻据,為了避免復雜性艾猜,從一誕生,JavaScript就是單線程,這已經成了這門語言的核心特征匆赃,將來也不會改變淤毛。

  為了利用多核CPU的計算能力,HTML5提出Web Worker標準算柳,允許JavaScript腳本創(chuàng)建多個線程低淡,但是子線程完全受主線程控制,且不得操作DOM瞬项。所以蔗蹋,這個新標準并沒有改變JavaScript單線程的本質。

  其實同步和異步囱淋,無論如何猪杭,做事情的時候都是只有一條流水線(單線程),同步和異步的差別就在于這條流水線上各個流程的執(zhí)行順序不同绎橘。

????????最基礎的異步是setTimeout和setInterval函數(shù)胁孙,很常見,但是很少人有人知道其實這就是異步称鳞,盡管我們設置了setTimeout(function涮较,time)中的等待時間為0,結果其中的function還是后執(zhí)行冈止。

? ??<script type="text/javascript">

? ? ? ? console.log( "1" );?

? ? ? ? setTimeout(function() {?

? ? ? ? ? ? console.log( "2" )?

? ? ? ? }, 0 );?

? ? ? ? setTimeout(function() {?

? ? ? ? ? ? console.log( "3" )?

? ? ? ? }, 0 );?

? ? ? ? setTimeout(function() {?

? ? ? ? ? ? console.log( "4" )?

? ? ? ? }, 0 );?

? ? ? ? console.log( "5" );?

</script>?

  火狐瀏覽器的api文檔有這樣一句話:Because even though setTimeout was called with a delay of zero, it's placed on a queue and scheduled to run at the next opportunity, not immediately. Currently executing code must complete before functions on the queue are executed, the resulting execution order may not be as expected.

  意思就是:盡管setTimeout的time延遲時間為0狂票,其中的function也會被放入一個隊列中,等待下一個機會執(zhí)行熙暴,當前的代碼(指不需要加入隊列中的程序)必須在該隊列的程序完成之前完成闺属,因此結果可能不與預期結果相同。

  這里說到了一個“隊列”(即任務隊列)周霉,該隊列放的是什么呢掂器,放的就是setTimeout中的function,這些function依次加入該隊列俱箱,即該隊列中所有function中的程序將會在該隊列以外的所有代碼執(zhí)行完畢之后再以此執(zhí)行国瓮,這是為什么呢?因為在執(zhí)行程序的時候狞谱,瀏覽器會默認setTimeout以及ajax請求這一類的方法都是耗時程序(盡管可能不耗時)乃摹,將其加入一個隊列中,該隊列是一個存儲耗時程序的隊列跟衅,在所有不耗時程序執(zhí)行過后孵睬,再來依次執(zhí)行該隊列中的程序。

  又回到了最初的起點——javascript是單線程伶跷。單線程就意味著掰读,所有任務需要排隊秘狞,前一個任務結束,才會執(zhí)行后一個任務蹈集。如果前一個任務耗時很長谒撼,后一個任務就不得不一直等著。于是就有一個概念——任務隊列雾狈。如果排隊是因為計算量大,CPU忙不過來抵皱,倒也算了善榛,但是很多時候CPU是閑著的,因為IO設備(輸入輸出設備)很慢(比如Ajax操作從網絡讀取數(shù)據(jù))呻畸,不得不等著結果出來移盆,再往下執(zhí)行。于是JavaScript語言的設計者意識到伤为,這時主線程完全可以不管IO設備咒循,掛起處于等待中的任務,先運行排在后面的任務绞愚。等到IO設備返回了結果叙甸,再回過頭,把掛起的任務繼續(xù)執(zhí)行下去位衩。

  于是裆蒸,所有任務可以分成兩種,一種是同步任務(synchronous)糖驴,另一種是異步任務(asynchronous)僚祷。同步任務指的是,在主線程上排隊執(zhí)行的任務贮缕,只有前一個任務執(zhí)行完畢辙谜,才能執(zhí)行后一個任務;異步任務指的是感昼,不進入主線程装哆、而進入"任務隊列"(task queue)的任務,只有等主線程任務執(zhí)行完畢抑诸,"任務隊列"開始通知主線程烂琴,請求執(zhí)行任務,該任務才會進入主線程執(zhí)行蜕乡。

具體來說奸绷,異步運行機制如下:

  (1)所有同步任務都在主線程上執(zhí)行层玲,形成一個執(zhí)行棧(execution context stack)号醉。

 》粗ⅰ(2)主線程之外,還存在一個"任務隊列"(task queue)畔派。只要異步任務有了運行結果铅碍,就在"任務隊列"之中放置一個事件。

 ∠咭(3)一旦"執(zhí)行棧"中的所有同步任務執(zhí)行完畢胞谈,系統(tǒng)就會讀取"任務隊列",看看里面有哪些事件憨愉。那些對應的異步任務烦绳,于是結束等待狀態(tài),進入執(zhí)行棧配紫,開始執(zhí)行径密。

  (4)主線程不斷重復上面的第三步躺孝。

  只要主線程空了享扔,就會去讀取"任務隊列",這就是JavaScript的運行機制植袍。這個過程會不斷重復惧眠。

  "任務隊列"是一個事件的隊列(也可以理解成消息的隊列),IO設備完成一項任務奋单,就在"任務隊列"中添加一個事件锉试,表示相關的異步任務可以進入"執(zhí)行棧"了。主線程讀取"任務隊列"览濒,就是讀取里面有哪些事件呆盖。

  "任務隊列"中的事件,除了IO設備的事件以外贷笛,還包括一些用戶產生的事件(比如鼠標點擊应又、頁面滾動等等),比如$(selectot).click(function)乏苦,這些都是相對耗時的操作株扛。只要指定過這些事件的回調函數(shù),這些事件發(fā)生時就會進入"任務隊列"汇荐,等待主線程讀取洞就。

  所謂"回調函數(shù)"(callback),就是那些會被主線程掛起來的代碼掀淘,前面說的點擊事件$(selectot).click(function)中的function就是一個回調函數(shù)旬蟋。異步任務必須指定回調函數(shù),當主線程開始執(zhí)行異步任務革娄,就是執(zhí)行對應的回調函數(shù)倾贰。例如ajax的success冕碟,complete,error也都指定了各自的回調函數(shù)匆浙,這些函數(shù)就會加入“任務隊列”中安寺,等待執(zhí)行。

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末首尼,一起剝皮案震驚了整個濱河市挑庶,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌软能,老刑警劉巖挠羔,帶你破解...
    沈念sama閱讀 216,744評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異埋嵌,居然都是意外死亡,警方通過查閱死者的電腦和手機俱恶,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,505評論 3 392
  • 文/潘曉璐 我一進店門雹嗦,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人合是,你說我怎么就攤上這事了罪。” “怎么了聪全?”我有些...
    開封第一講書人閱讀 163,105評論 0 353
  • 文/不壞的土叔 我叫張陵泊藕,是天一觀的道長。 經常有香客問我难礼,道長娃圆,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,242評論 1 292
  • 正文 為了忘掉前任蛾茉,我火速辦了婚禮讼呢,結果婚禮上,老公的妹妹穿的比我還像新娘谦炬。我一直安慰自己悦屏,他們只是感情好,可當我...
    茶點故事閱讀 67,269評論 6 389
  • 文/花漫 我一把揭開白布键思。 她就那樣靜靜地躺著础爬,像睡著了一般。 火紅的嫁衣襯著肌膚如雪吼鳞。 梳的紋絲不亂的頭發(fā)上看蚜,一...
    開封第一講書人閱讀 51,215評論 1 299
  • 那天,我揣著相機與錄音赖条,去河邊找鬼失乾。 笑死常熙,一個胖子當著我的面吹牛,可吹牛的內容都是我干的碱茁。 我是一名探鬼主播裸卫,決...
    沈念sama閱讀 40,096評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼纽竣!你這毒婦竟也來了墓贿?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 38,939評論 0 274
  • 序言:老撾萬榮一對情侶失蹤蜓氨,失蹤者是張志新(化名)和其女友劉穎聋袋,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體穴吹,經...
    沈念sama閱讀 45,354評論 1 311
  • 正文 獨居荒郊野嶺守林人離奇死亡幽勒,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,573評論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了港令。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片啥容。...
    茶點故事閱讀 39,745評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖顷霹,靈堂內的尸體忽然破棺而出咪惠,到底是詐尸還是另有隱情,我是刑警寧澤淋淀,帶...
    沈念sama閱讀 35,448評論 5 344
  • 正文 年R本政府宣布遥昧,位于F島的核電站,受9級特大地震影響朵纷,放射性物質發(fā)生泄漏炭臭。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,048評論 3 327
  • 文/蒙蒙 一袍辞、第九天 我趴在偏房一處隱蔽的房頂上張望徽缚。 院中可真熱鬧,春花似錦革屠、人聲如沸凿试。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,683評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽那婉。三九已至,卻和暖如春党瓮,著一層夾襖步出監(jiān)牢的瞬間详炬,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,838評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留呛谜,地道東北人在跳。 一個月前我還...
    沈念sama閱讀 47,776評論 2 369
  • 正文 我出身青樓,卻偏偏與公主長得像隐岛,于是被迫代替她去往敵國和親猫妙。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,652評論 2 354

推薦閱讀更多精彩內容

  • 昨晚閑來無事聚凹,隨手點開了這部《七十七天》割坠,畫面之美麗,令人震撼妒牙。 這部影劇里彼哼,兩個孤獨的男人女人,都是為了所謂的自...
    藍白的世界閱讀 787評論 0 47
  • 我們最終湘今,都變成了我們最討厭的樣子敢朱。面目可憎,張牙舞爪摩瞎。
    加勒比2016閱讀 97評論 0 0
  • 金剛智慧 1.金錢98%是能量蔫饰,2%是物質,金錢的本質是"侍奉生命愉豺、服務他人"。 2.財?shù)溃壕聪锩R颍锉M其用蚪拦。(...
    四川嘉佳文化閱讀 1,718評論 0 3
  • 薄霧輕煙,柔絲倦雨冻押,霏彌郁柳蓮塘路驰贷。晨昏如夜夢微涼,醒時幾辨身何處洛巢? 簾幕低垂括袒,隔窗閉戶,秋千院落無人度稿茉。娥眉淡挑...
    蘭貭冰心閱讀 336評論 1 8
  • 忽然想起一個朋友锹锰,曾經那么熟悉的朋友。只是今天卻是不再聯(lián)系漓库,有種憂傷恃慧,是因為我們不再熟悉,那種形同陌路的感覺渺蒿,在心...
    向行閱讀 301評論 6 3