nodejs Event Loop

1.前置知識
  • node.js
    是一個(gè)可以運(yùn)行js的平臺
    包括fs模塊藕甩、http模塊以及JS引擎(v8)

  • js引擎(單線程)
    同一時(shí)間只做一件事情,但是他也可以同一時(shí)間做多件事請风瘦,因?yàn)樗行值埽ㄆ渌€程)幫他做

比如:
對于一個(gè)ajax請求get('/1.json')凹蜈,若果這個(gè)請求需要100ms,那么我在這100ms內(nèi)觸發(fā)一個(gè)點(diǎn)擊事件讓它打印出一個(gè)1可以嗎糕伐?
答:可以砰琢,雖然說js是單線程,但是它可以主要是因?yàn)樗恼埱笞屗男值芫W(wǎng)絡(luò)模塊去做了良瞧,這時(shí)候js就處于空閑狀態(tài)陪汽,等到網(wǎng)絡(luò)模塊請求完成就會通知js,js然后就會去執(zhí)行一個(gè)回調(diào)

2.nodejs Event loop

2.1 當(dāng)nodejs啟動時(shí)褥蚯,會執(zhí)行三件事情

  1. 初始化event loop
  2. 開始執(zhí)行腳本
  3. 進(jìn)入event loop

2.2. 處理event loop經(jīng)歷的幾個(gè)階段(初始化的時(shí)候不會有這幾個(gè)階段)

上面的幾個(gè)階段中我們只需要了解紅框中的三個(gè)就可以了挚冤,并且每一個(gè)階段都有自己的一個(gè)隊(duì)列

  • timers階段
    處理setTimeout和setInterval中到時(shí)的回調(diào)函數(shù),對于timers中隊(duì)列的處理赞庶,setTimeout或setInterval中的函數(shù)都添加到隊(duì)列里训挡,同時(shí)記下來這些函數(shù)什么時(shí)間被調(diào)用到了調(diào)用時(shí)間就調(diào)用,沒到時(shí)間就進(jìn)入下一階段歧强,然后會停留在poll階段
  • poll階段
    輪詢階段
    比如上面說的讓兄弟(其他線程處理的請求任務(wù))澜薄,在這個(gè)階段會一直去問執(zhí)行相關(guān)任務(wù)的模塊任務(wù)執(zhí)行完了沒有,一旦任務(wù)執(zhí)行完成摊册,相關(guān)的數(shù)據(jù)就會放到一個(gè)回調(diào)里面然后加入到poll的隊(duì)列中肤京,也就是除了timers階段外的所有回調(diào)都是在poll這個(gè)階段處理的。poll階段會一直重復(fù)檢查剛才timers里沒有到時(shí)間的計(jì)時(shí)器有沒有到時(shí)間丧靡,如果到時(shí)間了蟆沫,就直接通過check到達(dá)timers階段通知timers執(zhí)行這個(gè)回調(diào),然后從timers隊(duì)列中清除
    check階段
    只處理setImmediate

2.3. 通過一個(gè)例子更加清楚的理解timers是怎么執(zhí)行的

比如一開始有兩個(gè)計(jì)時(shí)器一個(gè)4ms一個(gè)100ms
正常情況:當(dāng)?shù)谝淮蝨imers的時(shí)候4ms已經(jīng)到了所以直接執(zhí)行里面的函數(shù)然后從隊(duì)列中清除温治,然后第二個(gè)100ms并沒有到饭庞,就會進(jìn)入poll階段停留,poll階段會一直讀時(shí)間問100ms有沒有到熬荆,如果到了就直接通過check到timers然后通知它100ms到了執(zhí)行相關(guān)的回調(diào)舟山,從隊(duì)列中清除
特例:因?yàn)閜oll從4ms一直等到100ms所以這段空閑的時(shí)間如果有另一個(gè)請求執(zhí)行完了比如說是在90ms執(zhí)行完了,那么這個(gè)時(shí)候它會去執(zhí)行這個(gè)回調(diào)卤恳,但是這個(gè)函數(shù)調(diào)用也是需要時(shí)間的如果說調(diào)用用了20ms那么也就是說會在110ms的時(shí)候處理完這個(gè)函數(shù)的調(diào)用累盗,也就是會錯(cuò)過100ms這個(gè)時(shí)間點(diǎn),那么就會在110ms的時(shí)候通過check通知timers執(zhí)行100ms那個(gè)回調(diào)

2.4. 關(guān)于setTImeout和setImmediate的執(zhí)行順序
答:正常情況下是setImmediate先執(zhí)行突琳,只有第一次啟動nodejs的情況下timers里的定時(shí)器到時(shí)間了才可能setTimeout先執(zhí)行若债。

原因:因?yàn)閚odejs啟動會執(zhí)行三件事,開始執(zhí)行腳本也就是執(zhí)行你頁面的代碼拆融,這時(shí)候會執(zhí)行你的setTImeout蠢琳,然后才會去處理event loop啊终,而從執(zhí)行腳本到處理event loop中間也需要時(shí)間,setTimeout最小的時(shí)間是4ms傲须,如果從執(zhí)行腳本到處理event loop花了5ms時(shí)間蓝牲,那么一進(jìn)入timers就會發(fā)現(xiàn)時(shí)間到了就會立刻處理回調(diào),所以這時(shí)候setTimeout就會先執(zhí)行

nextTick

進(jìn)入每個(gè)階段前都會執(zhí)行泰讽,包括nodejs啟動的時(shí)候也會執(zhí)行

setTimeout(()=>{
  console.log('timeout')
})
setImmediate(()=>{
  console.log('immediate')
})
process.nextTick(()=>{
  console.log('next tick')
})
//next tick
//timeout
//immediate
Macro Task(宏任務(wù))&Micro Task(微任務(wù))

媽Ma 咪Mi
先執(zhí)行完一個(gè)宏任務(wù)再去執(zhí)行一個(gè)微任務(wù)例衍,微任務(wù)每次都要清空
setTimeout后面的回調(diào)還有當(dāng)前的腳本代碼都是宏任務(wù)
nextTick和Promise都屬于微任務(wù)

上圖中setTimeout里面的回調(diào)是宏任務(wù)所以會放到宏任務(wù)的下一個(gè)任務(wù)隊(duì)列中,而執(zhí)行完一個(gè)宏任務(wù)后緊接著要執(zhí)行一個(gè)微任務(wù)promise里面的是微任務(wù)已卸,所以接著執(zhí)行的是2佛玄,最后執(zhí)行3

重要題目:

console.log('script start');

setTimeout(function() {
  console.log('setTimeout');
}, 0);

let promise = new Promise((resolve, reject)=>{
    console.log(1)
    resolve()
})
promise.then(function() {
  console.log('promise1');
}).then(function() {
  console.log('promise2');
});

上面代碼執(zhí)行順序是?
答:
script start
1
promise1
promise2
setTimeout
原因:promise里面的代碼時(shí)立即執(zhí)行的所以在script start后緊接著是1累澡,而setTImeout里面的回調(diào)是宏任務(wù)翎嫡,當(dāng)前代碼就是宏任務(wù),所以需要在下個(gè)微任務(wù)后執(zhí)行永乌,promise.then里面的代碼都是微任務(wù),所以會先pormise最后setTimeout

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末具伍,一起剝皮案震驚了整個(gè)濱河市翅雏,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌人芽,老刑警劉巖望几,帶你破解...
    沈念sama閱讀 219,490評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異萤厅,居然都是意外死亡橄抹,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,581評論 3 395
  • 文/潘曉璐 我一進(jìn)店門惕味,熙熙樓的掌柜王于貴愁眉苦臉地迎上來楼誓,“玉大人,你說我怎么就攤上這事名挥∨备” “怎么了?”我有些...
    開封第一講書人閱讀 165,830評論 0 356
  • 文/不壞的土叔 我叫張陵禀倔,是天一觀的道長榄融。 經(jīng)常有香客問我,道長救湖,這世上最難降的妖魔是什么愧杯? 我笑而不...
    開封第一講書人閱讀 58,957評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮鞋既,結(jié)果婚禮上力九,老公的妹妹穿的比我還像新娘耍铜。我一直安慰自己,他們只是感情好畏邢,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,974評論 6 393
  • 文/花漫 我一把揭開白布业扒。 她就那樣靜靜地躺著,像睡著了一般舒萎。 火紅的嫁衣襯著肌膚如雪程储。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,754評論 1 307
  • 那天臂寝,我揣著相機(jī)與錄音章鲤,去河邊找鬼。 笑死咆贬,一個(gè)胖子當(dāng)著我的面吹牛败徊,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播掏缎,決...
    沈念sama閱讀 40,464評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼皱蹦,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了眷蜈?” 一聲冷哼從身側(cè)響起沪哺,我...
    開封第一講書人閱讀 39,357評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎酌儒,沒想到半個(gè)月后辜妓,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,847評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡忌怎,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,995評論 3 338
  • 正文 我和宋清朗相戀三年籍滴,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片榴啸。...
    茶點(diǎn)故事閱讀 40,137評論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡孽惰,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出鸥印,到底是詐尸還是另有隱情灰瞻,我是刑警寧澤,帶...
    沈念sama閱讀 35,819評論 5 346
  • 正文 年R本政府宣布辅甥,位于F島的核電站酝润,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏璃弄。R本人自食惡果不足惜要销,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,482評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望夏块。 院中可真熱鬧疏咐,春花似錦纤掸、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,023評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至酌壕,卻和暖如春掏愁,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背卵牍。 一陣腳步聲響...
    開封第一講書人閱讀 33,149評論 1 272
  • 我被黑心中介騙來泰國打工果港, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人糊昙。 一個(gè)月前我還...
    沈念sama閱讀 48,409評論 3 373
  • 正文 我出身青樓辛掠,卻偏偏與公主長得像,于是被迫代替她去往敵國和親释牺。 傳聞我的和親對象是個(gè)殘疾皇子萝衩,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,086評論 2 355

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