Node.js中的eventloop怎么用

這篇文章主要講解了“Node.js中的eventloop怎么用”,文中的講解內(nèi)容簡(jiǎn)單清晰,易于學(xué)習(xí)與理解,下面請(qǐng)大家跟著小編的思路慢慢深入,一起來研究和學(xué)習(xí)“Node.js中的eventloop怎么用”吧!

鳳凰ssl適用于網(wǎng)站、小程序/APP、API接口等需要進(jìn)行數(shù)據(jù)傳輸應(yīng)用場(chǎng)景,ssl證書未來市場(chǎng)廣闊!成為成都創(chuàng)新互聯(lián)公司的ssl證書銷售渠道,可以享受市場(chǎng)價(jià)格4-6折優(yōu)惠!如果有意向歡迎電話聯(lián)系或者加微信:13518219792(備注:SSL證書合作)期待與您的合作!

主線程從"任務(wù)隊(duì)列"中讀取事件,這個(gè)過程是循環(huán)不斷的,所以整個(gè)的這種運(yùn)行機(jī)制又稱為Event Loop(事件循環(huán))。

Node.js中的eventloop怎么用

其實(shí)在前面的文章我也講述過瀏覽器中的eventloop。然而在NodeJs中的eventloop與瀏覽器的是有區(qū)別的。對(duì)于寫nodejs的人來說掌握eventloop是一項(xiàng)很重要的技能。因?yàn)檫@意味著你不僅是會(huì)寫js,而對(duì)NodeJs也是有研究的。

為什么要有eventloop?

我們知道NodeJs的本質(zhì)是把瀏覽器的v8搬到了操作系統(tǒng)中運(yùn)行,因此也把瀏覽器的事件循環(huán)拿過來了??墒菫槭裁磿?huì)出現(xiàn)eventloop這樣的設(shè)計(jì)呢?

從歷史原因上來看,js在設(shè)計(jì)時(shí)只是一門很簡(jiǎn)單的為了在頁面上操作一下dom的語言(相信大家都聽過js只用了10天就設(shè)計(jì)出來的故事)。出于這個(gè)目標(biāo),我們當(dāng)然希望js的運(yùn)行盡可能的簡(jiǎn)單,輕量,有多輕呢?輕到j(luò)s的渲染引擎是在一個(gè)線程中運(yùn)行的。

那么問題來了如果是在一個(gè)線程上運(yùn)行js,當(dāng)代碼是線性的時(shí)候,當(dāng)然是沒有問題的。但在頁面上,我們需要用戶的交互,而這些交互是不知道為什么時(shí)候發(fā)生的。那js要怎么處理?如果眼前有正在運(yùn)行的代碼,一個(gè)用戶交互進(jìn)來之后,程序該怎么反應(yīng)?如果先處理用戶的交互,那原來的程序就會(huì)被暫停(也就是阻塞)。為了避免這種阻塞,js采用了一個(gè)辦法,就是用一個(gè)消息隊(duì)列,來存放這種用戶交互。等所有的程序跑完之后,再去消息隊(duì)列中拿交互事件,然后執(zhí)行。這樣就解決了阻塞的問題了。

瀏覽器的eventloop

我們都知道瀏覽器在瀏覽頁面的時(shí)候,用戶交互是隨時(shí)可能發(fā)生的,為了可以即時(shí)響應(yīng)用戶。js是不會(huì)關(guān)閉的,他會(huì)不停的循環(huán)。大致如下:

向消息隊(duì)列拿任務(wù)-->執(zhí)行任務(wù)-->執(zhí)行完畢--> 向消息隊(duì)列拿任務(wù)--> ....

當(dāng)然我們?cè)谥暗氖录h(huán)文章中講過,為了給不同的異步任務(wù)分類,在事件循環(huán)中其實(shí)是有宏任務(wù)和微任務(wù)的區(qū)分的。他們的執(zhí)行大致為

向消息隊(duì)列拿微任務(wù)-->執(zhí)行微任務(wù)-->微任務(wù)執(zhí)行完畢--> 向消息隊(duì)列拿宏任務(wù)-->執(zhí)行宏任務(wù)-->宏任務(wù)執(zhí)行完畢-->向消息隊(duì)列拿微任務(wù)-->...

NodeJs的eventloop

node的事件循環(huán)其實(shí)大致思路跟在瀏覽器上的是相似的,但nodeJs對(duì)不同的宏任務(wù)又作出了不同時(shí)期的區(qū)分。下面是官方的流程圖:

Node.js中的eventloop怎么用

可以看到nodeJs中每次事件循環(huán)被分成了具體的6個(gè)時(shí)期,每個(gè)時(shí)期會(huì)用指定的宏任務(wù)。然后在每個(gè)時(shí)期的宏任務(wù)執(zhí)行之前,會(huì)優(yōu)先執(zhí)行完微任務(wù)隊(duì)列。

總覽

timers執(zhí)行由setTimeout()setInterval()觸發(fā)的回調(diào)
pending callbacks執(zhí)行延遲到下一個(gè)循環(huán)迭代的I / O回調(diào)
idle, prepare只在內(nèi)部使用,開發(fā)者可以不關(guān)注
poll檢索新的I / O事件;執(zhí)行I / O相關(guān)的回調(diào)(會(huì)執(zhí)行幾乎所有的回調(diào),除了 close callbacks 以及 timers 調(diào)度的回調(diào)和 setImmediate() 調(diào)度的回調(diào),在恰當(dāng)?shù)臅r(shí)機(jī)將會(huì)阻塞在此階段)
check執(zhí)行setImmediate()
close callbacks比如socket.on('close', ...)

其實(shí)通過上述表格,我們已經(jīng)很清晰知道整個(gè)事件循環(huán)機(jī)制的執(zhí)行順序了。但可能大家還會(huì)有一些疑問。下面來詳細(xì)講一下。

pending callbacks

這個(gè)階段其實(shí)是處理由于操作系統(tǒng)出錯(cuò),導(dǎo)致一些本應(yīng)在上次事件循環(huán)中執(zhí)行的回調(diào)。例如一些TCP錯(cuò)誤。因此這部分,開發(fā)者不能主動(dòng)操作,是NodeJs的一些容錯(cuò)機(jī)制。

check

同樣的,setImmediate是nodejs特有的api,他可以立即創(chuàng)建一個(gè)異步宏任務(wù)。不僅如此,nodejs在事件循環(huán)中還專門設(shè)了一個(gè)check時(shí)期,在這個(gè)時(shí)期會(huì)專門執(zhí)行setImmediate的回調(diào)。甚至你可以在這個(gè)時(shí)期中如果不停的產(chǎn)生setImmediate回調(diào),eventloop會(huì)優(yōu)先處理。

close callbacks

這個(gè)時(shí)期處理關(guān)閉事件,如socket.on('close', ...)等這樣可以確保在一些通訊結(jié)束前,所有任務(wù)都完成了。

微任務(wù)在eventloop中

我們先來回顧瀏覽器與nodejs的差異:

宏任務(wù):

任務(wù)瀏覽器Node
I/O??
setTimeout??
setInterval??
setImmediate??
requestAnimationFrame??

微任務(wù):

任務(wù)瀏覽器Node
process.nextTick??
MutationObserver??
Promise.then catch finally??

可以看到process.nextTick是nodejs特有的微任務(wù),不僅如此,process.nextTick()的優(yōu)先級(jí)高于所有的微任務(wù),每一次清空微任務(wù)列表的時(shí)候,都是先執(zhí)行 process.nextTick()

執(zhí)行差異

不僅是任務(wù)類型上有差異,在執(zhí)行上2個(gè)環(huán)境其實(shí)也有差異。在瀏覽器上執(zhí)行任務(wù)的時(shí)候,每執(zhí)行一個(gè)宏任務(wù)之前,需要先確保微任務(wù)隊(duì)列執(zhí)行完了。而在nodejs上是每個(gè)時(shí)期之前,先確保微任務(wù)隊(duì)列執(zhí)行完。也就是說在假如在timer時(shí)期,會(huì)先把所有setTimeout,setInterval的宏任務(wù)執(zhí)行完。在執(zhí)行完微任務(wù),再進(jìn)入下個(gè)時(shí)期。

注意:以上執(zhí)行規(guī)則是在nodejs的v11版本之前的規(guī)則。在11版本之后nodejs的執(zhí)行輸出是跟瀏覽器一樣的。

setImmediate() vs setTimeout()

setImmediate() 和 setTimeout()的執(zhí)行先后順序是不一定的,就是說如果你不停地執(zhí)行以下代碼,每次得到的結(jié)果可能是不一樣的。

setTimeout(() => {
  console.log('timeout');
}, 0);

setImmediate(() => {
  console.log('immediate');
});

其中的原因是程序?qū)r(shí)間的處理是有誤差的。在setTimeout方法中設(shè)置的時(shí)間,不一定是準(zhǔn)確的。同時(shí)在回調(diào)觸發(fā)時(shí),也無法確認(rèn)事件循環(huán)處在哪個(gè)時(shí)期,可能是timer,也可能是check。所有會(huì)有不同的結(jié)果。

感謝各位的閱讀,以上就是“Node.js中的eventloop怎么用”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對(duì)Node.js中的eventloop怎么用這一問題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是創(chuàng)新互聯(lián),小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!

文章名稱:Node.js中的eventloop怎么用
鏈接地址:http://muchs.cn/article44/gpjcee.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)頁設(shè)計(jì)公司、微信公眾號(hào)標(biāo)簽優(yōu)化、App設(shè)計(jì)網(wǎng)站排名、服務(wù)器托管

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

外貿(mào)網(wǎng)站制作