搜尋
首頁web前端js教程Node.js事件驅動_node.js

Node.js事件驅動實作概覽

雖然在ECMAScript的標準裡並沒有(也沒有必要)明確規定“事件”,但是在瀏覽器中,事件作為一個極為重要的機制,給予JavaScript響應用戶操作與DOM變化的能力;在Node. js中,非同步事件驅動模型則是其高並發能力的基礎。

學習JavaScript也需要了解它的運行平台,為了更好的理解JavaScript的事件模型,我打算從Node及瀏覽器引擎源碼入手,分析其底層實現,並將我的分析整理為一系列博文;一方面作為筆記,另一方面也希望能與大家交流,分析理解有疏漏偏頗之處,還望各位斧正。

簡述事件驅動模型

解釋JavaScript事件模型本身的好文章已經很多了,可以說這已經是一個說爛了的話題,這裡我只簡單寫一下,並且提供一些好文章的連結。

程式如何回應事件

我們的程式回應外部的事件有以下兩種方式:

中斷

作業系統處理鍵盤等硬體輸入就是透過中斷來進行的,這個方式的好處是即使沒有多線程,我們也可以放心地執行我們的程式碼,CPU收到中斷訊號後自動地轉去執行對應的中斷處理程序,處理完成後會恢復原來的程式碼的執行環境繼續執行。這種方式需要硬體的支持,一般來說都會被作業系統封裝起來。

輪詢

循環偵測是否有事件發生,如果有就去執行對應的處理程序。這在底層和上層的開發都有應用。
Windows視窗程式就需要在主執行緒寫下如下程式碼,通常稱做訊息循環:

MSG msg = { };
while (GetMessage(&msg, NULL, 0, 0))
{
  TranslateMessage(&msg);
  DispatchMessage(&msg);
}

訊息循環不斷偵測是否有訊息(使用者的UI操作、系統訊息等)出現,有的話就分發訊息,呼叫對應的回呼函數處理。
輪詢方式的一個缺點就是:如果在主執行緒的訊息循環裡進行耗時操作,程式就無法及時回應新的訊息。這在JavaScript中表現明顯,以後還會提到這一點,並探討其解決方案。

然而JavaScript中並沒有類似訊息循環程式碼,我們只是簡單地註冊事件,然後等待被呼叫。這是因為瀏覽器、Node作為執行平台,已經將event loop實作了,JavaScript程式碼不需要介入到這個過程中,只需要安靜地等待被呼叫者。

Node中的event loop

透過Node源碼看event loop的實作

Node採用V8作為JavaScript的執行引擎,同時使用libuv實作事件驅動程式非同步I/O。其事件循環就是採用了libuv的預設事件循環。

在src/node.cc中,

Environment* env = CreateEnvironment(
    node_isolate,
    uv_default_loop(),
    context,
    argc,
    argv,
    exec_argc,
    exec_argv);

這段程式碼建立了一個node執行環境,可以看到第三行的uv_default_loop(),這是libuv庫中的一個函數,它會初始化uv庫本身以及其中的default_loop_struct,並傳回一個指向它的指標default_loop_ptr。
之後,Node會載入執行環境並完成一些設定操作,然後啟動event loop:

bool more;
do {
 more = uv_run(env->event_loop(), UV_RUN_ONCE);
 if (more == false) {
  EmitBeforeExit(env);
  // Emit `beforeExit` if the loop became alive either after emitting
  // event, or after running some callbacks.
  more = uv_loop_alive(env->event_loop());
  if (uv_run(env->event_loop(), UV_RUN_NOWAIT) != 0)
   more = true;
 }
} while (more == true);
code = EmitExit(env);
RunAtExit(env);
...

more用來識別是否進行下一輪循環。

env->event_loop()會傳回先前儲存在env中的default_loop_ptr,uv_run函式將以指定的UV_RUN_ONCE模式啟動libuv的event loop。在這個模式下,uv_run會至少處理一個事件:這意味著,如果目前事件佇列中沒有需要處理的I/O事件,uv_run會阻塞住,直到有I/O事件需要處理,或下一個計時器時間到。如果目前沒有I/O事件也沒有定時器事件,則uv_run傳回false。

接下來Node會依照more的狀況決定下一步操作:

如果more為true,則繼續執行下一輪loop。

如果more為false,表示已經沒有等待處理的事件了,EmitBeforeExit(env);觸發進程的'beforeExit'事件,檢查並處理對應的處理函數,完成後直接跳出迴圈。

最後觸發'exit'事件,執行對應的回呼函數,Node運行結束,後面會進行一些資源釋放操作。

在libuv中,定時器事件是直接在event loop中處理的,而I/O事件則分為兩類:

Network I/O是使用系統提供的非阻塞式I/O解決方案,例如在Linux上使用epoll,windows上使用IOCP。

檔案操作和DNS操作沒有(很好的)系統解決方案,因此libuv自建了線程池,在其中進行阻塞式I/O。

另外我們也可以將自訂的函數拋到執行緒池中運行,在運行結束後主執行緒會執行對應的回呼函數,不過Node並沒有將這項功能加入到JavaScript中,也就是說只用原生Node是無法在JavaScript中開啟新的執行緒進行並行執行的。

以上所述就是本文的全部內容了,希望大家能夠喜歡。

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
C和JavaScript:連接解釋C和JavaScript:連接解釋Apr 23, 2025 am 12:07 AM

C 和JavaScript通過WebAssembly實現互操作性。 1)C 代碼編譯成WebAssembly模塊,引入到JavaScript環境中,增強計算能力。 2)在遊戲開發中,C 處理物理引擎和圖形渲染,JavaScript負責遊戲邏輯和用戶界面。

從網站到應用程序:JavaScript的不同應用從網站到應用程序:JavaScript的不同應用Apr 22, 2025 am 12:02 AM

JavaScript在網站、移動應用、桌面應用和服務器端編程中均有廣泛應用。 1)在網站開發中,JavaScript與HTML、CSS一起操作DOM,實現動態效果,並支持如jQuery、React等框架。 2)通過ReactNative和Ionic,JavaScript用於開發跨平台移動應用。 3)Electron框架使JavaScript能構建桌面應用。 4)Node.js讓JavaScript在服務器端運行,支持高並發請求。

Python vs. JavaScript:比較用例和應用程序Python vs. JavaScript:比較用例和應用程序Apr 21, 2025 am 12:01 AM

Python更適合數據科學和自動化,JavaScript更適合前端和全棧開發。 1.Python在數據科學和機器學習中表現出色,使用NumPy、Pandas等庫進行數據處理和建模。 2.Python在自動化和腳本編寫方面簡潔高效。 3.JavaScript在前端開發中不可或缺,用於構建動態網頁和單頁面應用。 4.JavaScript通過Node.js在後端開發中發揮作用,支持全棧開發。

C/C在JavaScript口譯員和編譯器中的作用C/C在JavaScript口譯員和編譯器中的作用Apr 20, 2025 am 12:01 AM

C和C 在JavaScript引擎中扮演了至关重要的角色,主要用于实现解释器和JIT编译器。1)C 用于解析JavaScript源码并生成抽象语法树。2)C 负责生成和执行字节码。3)C 实现JIT编译器,在运行时优化和编译热点代码,显著提高JavaScript的执行效率。

JavaScript在行動中:現實世界中的示例和項目JavaScript在行動中:現實世界中的示例和項目Apr 19, 2025 am 12:13 AM

JavaScript在現實世界中的應用包括前端和後端開發。 1)通過構建TODO列表應用展示前端應用,涉及DOM操作和事件處理。 2)通過Node.js和Express構建RESTfulAPI展示後端應用。

JavaScript和Web:核心功能和用例JavaScript和Web:核心功能和用例Apr 18, 2025 am 12:19 AM

JavaScript在Web開發中的主要用途包括客戶端交互、表單驗證和異步通信。 1)通過DOM操作實現動態內容更新和用戶交互;2)在用戶提交數據前進行客戶端驗證,提高用戶體驗;3)通過AJAX技術實現與服務器的無刷新通信。

了解JavaScript引擎:實施詳細信息了解JavaScript引擎:實施詳細信息Apr 17, 2025 am 12:05 AM

理解JavaScript引擎內部工作原理對開發者重要,因為它能幫助編寫更高效的代碼並理解性能瓶頸和優化策略。 1)引擎的工作流程包括解析、編譯和執行三個階段;2)執行過程中,引擎會進行動態優化,如內聯緩存和隱藏類;3)最佳實踐包括避免全局變量、優化循環、使用const和let,以及避免過度使用閉包。

Python vs. JavaScript:學習曲線和易用性Python vs. JavaScript:學習曲線和易用性Apr 16, 2025 am 12:12 AM

Python更適合初學者,學習曲線平緩,語法簡潔;JavaScript適合前端開發,學習曲線較陡,語法靈活。 1.Python語法直觀,適用於數據科學和後端開發。 2.JavaScript靈活,廣泛用於前端和服務器端編程。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

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

AI Clothes Remover

AI Clothes Remover

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

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

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

熱工具

PhpStorm Mac 版本

PhpStorm Mac 版本

最新(2018.2.1 )專業的PHP整合開發工具

MantisBT

MantisBT

Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。

SublimeText3 Mac版

SublimeText3 Mac版

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

MinGW - Minimalist GNU for Windows

MinGW - Minimalist GNU for Windows

這個專案正在遷移到osdn.net/projects/mingw的過程中,你可以繼續在那裡關注我們。 MinGW:GNU編譯器集合(GCC)的本機Windows移植版本,可自由分發的導入函式庫和用於建置本機Windows應用程式的頭檔;包括對MSVC執行時間的擴展,以支援C99功能。 MinGW的所有軟體都可以在64位元Windows平台上運作。

WebStorm Mac版

WebStorm Mac版

好用的JavaScript開發工具