一文帶你了解Node.js中的eventloop
主執行緒從"任務佇列"讀取事件,這個過程是循環不斷的,所以整個的這種運作機制又稱為Event Loop(事件循環)。以下這篇文章就來帶大家掌握Node.js中的eventloop,希望對大家有幫助!
其實在前面的文章我也講述過瀏覽器中的eventloop。然而在NodeJs中的eventloop與瀏覽器的卻是有差別的。對於寫nodejs的人來說掌握eventloop是一項很重要的技能。因為這代表你不只是會寫js,而對NodeJs也是有研究的。
為什麼要有eventloop?
我們知道NodeJs的本質是把瀏覽器的v8搬到了作業系統中運行,因此也把瀏覽器的事件循環拿過來了。可是為什麼會出現eventloop這樣的設計呢?
從歷史原因來看,js在設計時只是一門很簡單的為了在頁面上操作一下dom的語言(相信大家都聽過js只花了10天就設計出來的故事)。基於這個目標,我們當然希望js的運作盡可能的簡單,輕量,有多輕呢?輕到js的渲染引擎是在一個執行緒中運行的。
那麼問題來瞭如果是在一個執行緒上執行js,當程式碼是線性的時候,當然是沒有問題的。但在頁面上,我們需要使用者的交互,而這些交互是不知道為什麼時候會發生的。那js要怎麼處理?如果眼前有正在運作的程式碼,一個使用者互動進來之後,程式該怎麼反應?如果先處理使用者的交互,那原來的程式就會被暫停(也就是阻塞)。為了避免這種阻塞,js採用了一個辦法,就是用一個訊息佇列,來存放這種使用者互動。等所有的程式跑完之後,再去訊息佇列中拿互動事件,然後執行。這樣就解決了阻塞的問題了。
瀏覽器的eventloop
我們都知道瀏覽器在瀏覽頁面的時候,使用者互動是隨時可能發生的,為了可以即時回應使用者。 js是不會關閉的,他會不停的循環。大致如下:
向消息队列拿任务-->执行任务-->执行完毕--> 向消息队列拿任务--> ....
當然我們在之前的事件循環文章中講過,為了給不同的非同步任務分類,在事件循環中其實是有宏任務和微任務的區分的。他們的執行大致為
向消息队列拿微任务-->执行微任务-->微任务执行完毕--> 向消息队列拿宏任务-->执行宏任务-->宏任务执行完毕-->向消息队列拿微任务-->...
NodeJs的eventloop
#node的事件循環其實大致思路跟在瀏覽器上的是相似的,但nodeJs對不同的宏任務又作出了不同時期的區分。下面是官方的流程圖:
可以看到nodeJs中每次事件循環被分成了具體的6個時期,每個時期會用指定的巨集任務。然後在每個時期的巨集任務執行之前,會優先執行完微任務佇列。
總覽
#timers | 執行由setTimeout() 和setInterval() 觸發的回呼 | |
---|---|---|
#pending callbacks | ##執行延遲到下一個循環迭代的I / O回呼||
idle, prepare | 只在內部使用,開發者可以不關注||
poll | 檢索新的I / O事件;執行I / O相關的回呼(會執行幾乎所有的回調,除了close callbacks 以及timers 調度的回調和setImmediate() 調度的回調,在適當的時機將會阻塞在此階段)||
check | 執行setImmediate() | |
close callbacks | 例如socket.on('close', ...) |
任务 | 浏览器 | Node |
---|---|---|
I/O | ✅ | ✅ |
setTimeout | ✅ | ✅ |
setInterval | ✅ | ✅ |
setImmediate | ❌ | ✅ |
requestAnimationFrame | ✅ | ❌ |
微任务:
任务 | 浏览器 | Node |
---|---|---|
process.nextTick | ❌ | ✅ |
MutationObserver | ✅ | ❌ |
Promise.then catch finally | ✅ | ✅ |
可以看到process.nextTick是nodejs特有的微任务,不仅如此,process.nextTick()的优先级高于所有的微任务,每一次清空微任务列表的时候,都是先执行 process.nextTick()
执行差异
不仅是任务类型上有差异,在执行上2个环境其实也有差异。在浏览器上执行任务的时候,每执行一个宏任务之前,需要先确保微任务队列执行完了。而在nodejs上是每个时期之前,先确保微任务队列执行完。也就是说在假如在timer时期,会先把所有setTimeout,setInterval的宏任务执行完。在执行完微任务,再进入下个时期。
注意:以上执行规则是在nodejs的v11版本之前的规则。在11版本之后nodejs的执行输出是跟浏览器一样的。
setImmediate() vs setTimeout()
setImmediate() 和 setTimeout()的执行先后顺序是不一定的,就是说如果你不停地执行以下代码,每次得到的结果可能是不一样的。
setTimeout(() => { console.log('timeout'); }, 0); setImmediate(() => { console.log('immediate'); });
其中的原因是程序对时间的处理是有误差的。在setTimeout方法中设置的时间,不一定是准确的。同时在回调触发时,也无法确认事件循环处在哪个时期,可能是timer,也可能是check。所有会有不同的结果。
总结
eventloop是js运行机制里的重点内容,对于NodeJs来说,eventloop的操作空间则更大。因为它被细分为不同的时期,从而让我们可能把逻辑进一步细化。同时利用nextTick的最高优先级,可以写出在浏览器无法实现的代码。因此对于深入NodeJs的开发者来说,eventloop往往是他们考察新人对NodeJs理解的第一步。
更多node相关知识,请访问:nodejs 教程!!
以上是一文帶你了解Node.js中的eventloop的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

基於無阻塞、事件驅動建立的Node服務,具有記憶體消耗低的優點,非常適合處理海量的網路請求。在海量請求的前提下,就需要考慮「記憶體控制」的相關問題了。 1. V8的垃圾回收機制與記憶體限制 Js由垃圾回收機

選擇一個Node的Docker映像看起來像是小事,但是映像的大小和潛在漏洞可能會對你的CI/CD流程和安全造成重大的影響。那我們要如何選擇一個最好Node.js Docker映像呢?

Node 19已正式發布,以下這篇文章就來帶大家詳解了解Node.js 19的 6 大特性,希望對大家有幫助!

文件模組是對底層文件操作的封裝,例如文件讀寫/打開關閉/刪除添加等等文件模組最大的特點就是所有的方法都提供的**同步**和**異步**兩個版本,具有sync 字尾的方法都是同步方法,沒有的都是異

事件循環是 Node.js 的基本組成部分,透過確保主執行緒不被阻塞來實現非同步編程,了解事件循環對建立高效應用程式至關重要。以下這篇文章就來帶大家深入了解Node中的事件循環 ,希望對大家有幫助!

如何用pkg打包nodejs可執行檔?以下這篇文章跟大家介紹一下使用pkg將Node專案打包為執行檔的方法,希望對大家有幫助!
