做者 • Dhanjiv Pandey • 本文出處 • 已得到中譯受權
• 做者twitter
• 譯者主頁node
譯者按: 2018年的文章,其中部分問題放在今天仍然不算過期。
簡單的說 Node.js 就是運行在服務端的 JavaScript。 是一個基於Chrome JavaScript 運行時創建的一個平臺。 c++
Node.js是一個事件驅動I/O服務端JavaScript環境,基於Google的V8引擎,V8引擎執行Javascript的速度很是快,性能很是好。 web
Node.js是單線程的,它採用基於事件循環的併發模型。它不會阻塞代碼運行 (譯者:非阻塞I/O模型) ,而是註冊一個容許應用程序繼續運行的回調。這意味着Node.js能夠處理併發操做而無需建立多個執行線程,所以能夠很好地擴展 (譯者:處理併發操做和擴展有什麼直接關係?)。 是構建運行在分佈式設備上的數據密集型實時程序的完美選擇。shell
如下是使用Node.js的最佳領域:express
同時,它不適合那些佔用較多CPU使用量的大型應用程序。編程
讓咱們看一下Node.js的一些關鍵功能。segmentfault
咱們何時應該使用Node.js?瀏覽器
使用Node.js來開發流媒體或基於事件的實時應用程序是很是理想的,這些應用程序須要更少的CPU使用,好比:安全
Node.js很是適合須要同時處理數千個用戶請求的服務。服務器
什麼時候不使用Node.js?
下面列出了開發node.js應用程序最經常使用的IDE:
(譯者:VSCode不寫嗎???VSCode吹爆!)
Node.js應用程序在調用時建立一個線程。每當Node.js收到請求時,服務器都會先完成其處理,而後再處理下一個請求。
Node.js經過使用事件循環和回調函數來異步工做,以並行處理多個請求。事件循環是一種處理外部事件並將其轉換爲回調函數的功能。它在適當的時間調用全部事件處理程序。這樣,在處理單個請求時,大量工做是在後臺完成的,所以,若是處理未完成,新的傳入請求也沒必要等待。
在處理請求時,Node.js會向其附加一個回調函數,並將其移至後臺。如今,只要它的響應準備好了,就會調用一個事件,該事件觸發關聯的回調函數發送此響應。
讓咱們以雜貨店送貨爲例。
一般,送貨員到每一個房子去運送包裹。Node.js以相同的方式工做,而且一次處理一個請求。當任何一所房子沒有打開時,就會出現問題。送貨員不能在一所房子停下來等它打開。他接下來要作的是打電話給房主,並要求他在房屋開門時打電話。同時,他將去其餘地方送貨。Node.js的工做方式相同。它不等待請求處理完成(房屋開放)。相反,它附加了一個回調函數(房屋全部者的呼叫)。每當請求處理完成(房屋開放)時,都會調用一個事件,該事件觸發關聯的回調函數發送響應。
To summarize, Node.js does not process the requests in parallel. Instead, all the back-end processes like, I/O operations, heavy computation tasks, that take a lot of time to execute, run in parallel with other requests.
總而言之,Node.js不會並行處理請求(單線程一次處理一個)。全部後臺進程,如I/O操做、耗費大量時間執行的繁重計算任務,都與其餘請求並行運行 (譯者:這句話沒有理解)。
REPL表明 「Read Eval Print Loop」。這是一個簡單的程序,它接受命令,計算它們,最後打印結果。REPL提供了相似於Unix/Linux shell或窗口控制檯的環境,咱們能夠在其中輸入命令,而後系統用輸出進行響應。REPL執行如下任務:
是的,Node.js確實在一個線程上處理全部請求。但這只是Node.js設計理論的一部分。實際上,與單線程機制相比,它使用事件和回調來處理更大的異步請求。
此外,Node.js的優化設計利用了JavaScript和C++來保高性能。JavaScript經過Google Chrome v8引擎在服務器端執行。c++ lib的UV庫經過後臺來處理非順序的I/O。
爲了進行實際說明,讓咱們假設在Node.js隊列中排列了100個請求。按照設計,Node.js事件循環的主線線程將接收全部事件並轉發給後臺worker執行。一旦後臺worker處理完請求,註冊的回調將在事件循環線程上獲得通知,將結果傳遞迴用戶。
下面是使用Node.js獲取Post數據的代碼片斷:
app.use(express.bodyParser()); app.post('/', function(request, response){ console.log(request.body.user); });
下面是使用Node.js發出Post請求的代碼片斷:
var request = require('request'); request.post( 'http://www.example.com/action', { form: { key: 'value' } }, function (error, response, body) { if (!error && response.statusCode == 200) { console.log(body) } } );
咱們能夠調用「回調」做爲一個異步等效函數。Node.js大量使用回調,並在任務完成時觸發回調。Node.js的全部API均以支持回調的方式編寫。
例如,假設咱們有一個讀取文件的函數,當它開始讀取文件時,Node.js當即將控制權返回到執行環境,以便下一條指令能夠執行。一旦文件讀取操做完成,它將調用回調函數並將文件內容做爲參數傳遞。所以文件I/O,沒有阻塞或等待。此功能使Node.js具備高度可伸縮性,使用它能夠處理大量請求,而無需等待任何函數返回指望的結果。
例如,假設咱們有一個讀取文件的函數,當它開始讀取文件時,Node.js當即將控制返回到執行環境,以便執行下一條指令。一旦文件讀取操做完成,它將調用回調函數並傳遞文件的內容做爲參數。所以,沒有阻塞或等待,因爲文件I/O。這個功能使得Node.js具備高度的可擴展性,使用它能夠處理大量的請求,而不須要等待任何函數返回預期的結果。