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中開啟新的執行緒進行並行執行的。
以上所述就是本文的全部內容了,希望大家能夠喜歡。

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

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

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

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

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

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

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

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


熱AI工具

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

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

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

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

熱門文章

熱工具

PhpStorm Mac 版本
最新(2018.2.1 )專業的PHP整合開發工具

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

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

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

WebStorm Mac版
好用的JavaScript開發工具