若是你瞭解過Node.js
,那麼你必定據說過事件循環。你必定想知道它爲何那麼特殊,而且爲何你須要關注它?此時此刻的你,可能已經寫過許多基於Express.js
的後端代碼,但沒有接觸到任何的循環。編程
在下文中,咱們會先在一個更高的,無關操做系統的層面上了解事件循環,而後再去深刻到Node.js
中觀察它。後端
在事件循環裏,有兩個主要角色:併發
事件異步
事件處理器,即這些事件的訂閱者svg
事件,能夠是十分底層的操做系統事件,如「文件已經準備好被寫入」或「收到了一個新的HTTP請求」。
事件處理器,則是當指定事件觸發時,執行的一段代碼。函數
事件循環的職責,就是不斷得等待事件的發生,而後將這個事件的全部處理器,以它們訂閱這個事件的時間順序,依次執行。當這個事件的全部處理器都被執行完畢以後,事件循環就會開始繼續等待下一個事件的觸發,不斷往復。oop
當同時併發地處理多個請求時,以上的概念也是正確的,能夠這樣理解:在單個的線程中,事件處理器是一個一個按順序執行的。性能
即若是某個事件綁定了兩個處理器,那麼第二個處理器會在第一個處理器執行完畢後,纔開始執行。在這個事件的全部處理器都執行完畢以前,事件循環不會去檢查是否有新的事件觸發。在單個線程中,一切都是有順序地一個一個地執行的!spa
一個有趣並且常會出現的狀況是,在執行一個事件處理器的代碼裏,代碼觸發了另外一個事件。例如,在文件能夠被讀以後,這個事件的處理器開始讀取內容,期間處理器又觸發了一個寫事件,來將這個文件中已讀取的這部份內容響應給正在處理的HTTP請求。寫入完畢以後,繼續讀取文件。這就是事件循環保持運做的方式。操作系統
事件被觸發,而後以訂閱順序執行處理器,不斷往復。這個循環圈就是事件循環控制流的關鍵 ,在沒有更多的訂閱事件的處理器以後,Node.js
就會退出。
事件在實質上是從哪裏來?事件循環會不斷獲取下一個被觸發的事件,這是如何發生的?你是對的,這須要操做系統的幫助。幸運的是,現代操做系統中有許多方式能夠實現這些(select
,epoll
,kqueue
,IOCP
)。在平常使用時,一般會在操做系統提供的這些方式上會再抽象出一層(在Node.js
中,就是libuv
)。
另外一個須要操做系統幫助的,就是事件的訂閱,如註冊在特定的事件發生時須要執行的代碼。這也是事件循環中必需要實現的。
Node.js
中的事件循環事件循環是Node.js
中很是核心的組成部分,許多Node.js
的特性都依賴於它,它既有積極的影響也很差的影響。好比在處理I/O密集任務時的性能提高和缺少足夠信息量的錯誤堆棧信息。Node.js
異步回調驅動的編程範式,便直接是源於事件循環的存在。
每個Node.js
進程中都存在一個事件循環。只要進程存在,它就存在,一直不間斷地調度執行着你程序中的方法和操做系統方法。事件循環以一個無限循環的形式啓動,存在於Node.js
二進制文件裏main
函數的最後,當沒有更多可被執行的事件處理器時,它就退出。它運行於單個線程中,而且事件處理器是一個接一個順序執行的。