js中的同步和異步的理解

你應(yīng)該知道亿柑,javascript語言是一門“單線程”的語言,不像java語言亮曹,類繼承Thread再來個thread.start就可以開辟一個線程橄杨,所以秘症,javascript就像一條流水線,僅僅是一條流水線而已乡摹,要么加工采转,要么包裝,不能同時進(jìn)行多個任務(wù)和流程板熊。

那么這里說的同步和異步到底是什么呢察绷?如果你真的不懂,我希望你認(rèn)真讀完這篇文章容劳。其實我個人覺得js官方的文檔在使用兩個詞的時候并不準(zhǔn)確闸度,包括很多其他詞匯,都只是聽起來高深留量,但實際應(yīng)用好像跟這些詞沒半毛錢關(guān)系哟冬。例如“事件委托”這個詞,不知道的人乍一看誰又能說出“事件委托”是什么意思孝赫?委托什么事件红符?怎么個委托,我看不如干脆就叫“事件在外層元素中的捕獲”预侯,雖然長一點,一下就能看懂双戳。

回歸正軌糜芳,“同步”——一下就讓人想到“一起”這個詞魄衅;“異步”呢塘辅,從字面來講,好像是在不同的(異)的ways上do something扣墩,那首先想到的詞可能是“一邊...一邊...”,比如‘小明一邊吃雪糕一邊寫作業(yè)’,這完全沒毛病荆责,雪糕吃完了亚脆,作業(yè)也寫完了濒持,這就是異步?那就大錯特錯了弥喉!

其實同步和異步由境,無論如何蓖议,做事情的時候都是只有一條流水線(單線程),同步和異步的差別就在于這條流水線上各個流程的執(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>
圖片.png

可見笛钝,盡管我們設(shè)置了setTimeout(function愕宋,time)中的等待時間為0,結(jié)果其中的function還是后執(zhí)行囤捻。

火狐瀏覽器的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也會被放入一個隊列中,等待下一個機(jī)會執(zhí)行誊涯,當(dāng)前的代碼(指不需要加入隊列中的程序)必須在該隊列的程序完成之前完成,因此結(jié)果可能不與預(yù)期結(jié)果相同醋拧。

這里說到了一個“隊列”(即任務(wù)隊列)丹壕,該隊列放的是什么呢,放的就是setTimeout中的function缭乘,這些function依次加入該隊列琉用,即該隊列中所有function中的程序?qū)谠撽犃幸酝獾乃写a執(zhí)行完畢之后再以此執(zhí)行,這是為什么呢奴紧?因為在執(zhí)行程序的時候晶丘,瀏覽器會默認(rèn)setTimeout以及ajax請求這一類的方法都是耗時程序(盡管可能不耗時),將其加入一個隊列中沫浆,該隊列是一個存儲耗時程序的隊列滚秩,在所有不耗時程序執(zhí)行過后,再來依次執(zhí)行該隊列中的程序本股。

又回到了最初的起點——javascript是單線程痊末。單線程就意味著哩掺,所有任務(wù)需要排隊,前一個任務(wù)結(jié)束盒件,才會執(zhí)行后一個任務(wù)。如果前一個任務(wù)耗時很長恩沽,后一個任務(wù)就不得不一直等著翔始。于是就有一個概念——任務(wù)隊列。如果排隊是因為計算量大城瞎,CPU忙不過來脖镀,倒也算了,但是很多時候CPU是閑著的弦蹂,因為IO設(shè)備(輸入輸出設(shè)備)很慢(比如Ajax操作從網(wǎng)絡(luò)讀取數(shù)據(jù))强窖,不得不等著結(jié)果出來,再往下執(zhí)行翅溺。于是JavaScript語言的設(shè)計者意識到未巫,這時主線程完全可以不管IO設(shè)備启昧,掛起處于等待中的任務(wù),先運(yùn)行排在后面的任務(wù)握爷。等到IO設(shè)備返回了結(jié)果新啼,再回過頭,把掛起的任務(wù)繼續(xù)執(zhí)行下去燥撞。

于是物舒,所有任務(wù)可以分成兩種冠胯,一種是同步任務(wù)(synchronous),另一種是異步任務(wù)(asynchronous)荠察。同步任務(wù)指的是悉盆,在主線程上排隊執(zhí)行的任務(wù),只有前一個任務(wù)執(zhí)行完畢廷雅,才能執(zhí)行后一個任務(wù)京髓;異步任務(wù)指的是堰怨,不進(jìn)入主線程辞色、而進(jìn)入"任務(wù)隊列"(task queue)的任務(wù)揽涮,只有等主線程任務(wù)執(zhí)行完畢,"任務(wù)隊列"開始通知主線程盾似,請求執(zhí)行任務(wù)雪标,該任務(wù)才會進(jìn)入主線程執(zhí)行。

具體來說告抄,異步運(yùn)行機(jī)制如下:

(1)所有同步任務(wù)都在主線程上執(zhí)行打洼,形成一個執(zhí)行棧(execution context stack)龄糊。
(2)主線程之外绎签,還存在一個"任務(wù)隊列"(task queue)酝锅。只要異步任務(wù)有了運(yùn)行結(jié)果,就在"任務(wù)隊列"之中放置一個事件爸舒。
(3)一旦"執(zhí)行棧"中的所有同步任務(wù)執(zhí)行完畢稿蹲,系統(tǒng)就會讀取"任務(wù)隊列",看看里面有哪些事件涂炎。那些對應(yīng)的異步任務(wù)设哗,于是結(jié)束等待狀態(tài)网梢,進(jìn)入執(zhí)行棧战虏,開始執(zhí)行拣宰。
(4)主線程不斷重復(fù)上面的第三步。

[圖片上傳失敗...(image-9119a8-1530493547453)]

只要主線程空了烦感,就會去讀取"任務(wù)隊列"巡社,這就是JavaScript的運(yùn)行機(jī)制。這個過程會不斷重復(fù)手趣。

"任務(wù)隊列"是一個事件的隊列(也可以理解成消息的隊列)重贺,IO設(shè)備完成一項任務(wù),就在"任務(wù)隊列"中添加一個事件回懦,表示相關(guān)的異步任務(wù)可以進(jìn)入"執(zhí)行棧"了。主線程讀取"任務(wù)隊列"次企,就是讀取里面有哪些事件怯晕。
"任務(wù)隊列"中的事件,除了IO設(shè)備的事件以外缸棵,還包括一些用戶產(chǎn)生的事件(比如鼠標(biāo)點擊舟茶、頁面滾動等等),比如(selectot).click(function)隧出,這些都是相對耗時的操作。只要指定過這些事件的回調(diào)函數(shù)凄诞,這些事件**發(fā)生時**就會進(jìn)入"任務(wù)隊列",等待主線程讀取汛蝙。 所謂"回調(diào)函數(shù)"(callback),就是那些會被主線程掛起來的代碼,前面說的點擊事件(selectot).click(function)中的function就是一個回調(diào)函數(shù)器瘪。異步任務(wù)必須指定回調(diào)函數(shù),當(dāng)主線程開始執(zhí)行異步任務(wù)住拭,就是執(zhí)行對應(yīng)的回調(diào)函數(shù)。例如ajax的success,complete刘离,error也都指定了各自的回調(diào)函數(shù)茧痕,這些函數(shù)就會加入“任務(wù)隊列”中,等待執(zhí)行埃脏。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末堵幽,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子殴胧,更是在濱河造成了極大的恐慌报强,老刑警劉巖秉溉,帶你破解...
    沈念sama閱讀 217,657評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件弄跌,死亡現(xiàn)場離奇詭異俺猿,居然都是意外死亡凯肋,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,889評論 3 394
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事狈定。” “怎么了?”我有些...
    開封第一講書人閱讀 164,057評論 0 354
  • 文/不壞的土叔 我叫張陵流礁,是天一觀的道長神帅。 經(jīng)常有香客問我元镀,道長讨永,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,509評論 1 293
  • 正文 為了忘掉前任旋恼,我火速辦了婚禮嫩海,結(jié)果婚禮上奕谭,老公的妹妹穿的比我還像新娘血柳。我一直安慰自己膝宁,他們只是感情好员淫,可當(dāng)我...
    茶點故事閱讀 67,562評論 6 392
  • 文/花漫 我一把揭開白布击敌。 她就那樣靜靜地躺著刃宵,像睡著了一般徘公。 火紅的嫁衣襯著肌膚如雪步淹。 梳的紋絲不亂的頭發(fā)上澈驼,一...
    開封第一講書人閱讀 51,443評論 1 302
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼宽气。 笑死袄琳,一個胖子當(dāng)著我的面吹牛燃乍,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播宛琅,決...
    沈念sama閱讀 40,251評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼刻蟹,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了嘿辟?” 一聲冷哼從身側(cè)響起舆瘪,我...
    開封第一講書人閱讀 39,129評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎红伦,沒想到半個月后英古,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,561評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡昙读,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,779評論 3 335
  • 正文 我和宋清朗相戀三年召调,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蛮浑。...
    茶點故事閱讀 39,902評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡唠叛,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出沮稚,到底是詐尸還是另有隱情艺沼,我是刑警寧澤,帶...
    沈念sama閱讀 35,621評論 5 345
  • 正文 年R本政府宣布蕴掏,位于F島的核電站澳厢,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏囚似。R本人自食惡果不足惜剩拢,卻給世界環(huán)境...
    茶點故事閱讀 41,220評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望饶唤。 院中可真熱鬧徐伐,春花似錦、人聲如沸募狂。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,838評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽祸穷。三九已至性穿,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間雷滚,已是汗流浹背需曾。 一陣腳步聲響...
    開封第一講書人閱讀 32,971評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人呆万。 一個月前我還...
    沈念sama閱讀 48,025評論 2 370
  • 正文 我出身青樓商源,卻偏偏與公主長得像,于是被迫代替她去往敵國和親谋减。 傳聞我的和親對象是個殘疾皇子牡彻,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,843評論 2 354

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

  • 1.ios高性能編程 (1).內(nèi)層 最小的內(nèi)層平均值和峰值(2).耗電量 高效的算法和數(shù)據(jù)結(jié)構(gòu)(3).初始化時...
    歐辰_OSR閱讀 29,385評論 8 265
  • 1.個人覺得,js中出爹,最基礎(chǔ)的異步是setTimeout和setInterval函數(shù)庄吼,很常見,但是很少人有人知道其...
    神秘者007閱讀 523評論 0 0
  • 最基礎(chǔ)的異步是setTimeout和setInterval函數(shù)很常見严就,但是很少人有人知道其實這就是異步霸褒,因為它們可...
    FF_C閱讀 432評論 0 0
  • 從哪說起呢? 單純講多線程編程真的不知道從哪下嘴盈蛮。。 不如我直接引用一個最簡單的問題技矮,以這個作為切入點好了 在ma...
    Mr_Baymax閱讀 2,757評論 1 17
  • 一抖誉、預(yù)測,還是擲骰子 每每到年初衰倦,很多公司都會組織大量中高層管理者進(jìn)行新一年的業(yè)務(wù)預(yù)測袒炉。各個公司的業(yè)務(wù)預(yù)測風(fēng)格多樣...
    邏輯心世界閱讀 393評論 0 1