Loading...

隨著 Node.js 的問世,前端開發者的觸角也逐漸蔓延到後端,甚至透過 Electron.js 這類強大的套件,也可以製作出完整的桌面 GUI 應用程式;藉由 Node.js,前端開發者得以使用較為熟悉的 JavaScript 為敲門磚,逐步的拓展自己的技術守備範圍。但為什麼為了網頁而生的語言可以透過 Node.js 跑在伺服器端呢?要解開這個問題,就得從認識 Node.js 出發。

8週後端開發實務,學會用Node.js開發兼具前後端的Web App

Node.js

Node.js 是什麼呢?根據官網的說法:

Node.js® is a JavaScript runtime built on Chrome's V8 JavaScript engine.

「runtime」 指的是執行環境,就如同網頁上的 JavaScript 是在瀏覽器的 JavaScript 引擎上執行,Node.js 就是一個能執行 JavaScript 的環境,而 V8 則是主流瀏覽器 - Google Chrome 的 JavaScript 引擎,負責解析、執行 JavaScript,也就是負責實踐 ECMAScript 規範中定義的部份;另外,V8 是開源的專案,有興趣的讀者可以參照 Google Git - V8

Node.js 以 V8 為核心,加上一系列 C/C++ 的套件,成功的讓 Server 端也可以執行 JavaScript。

node-js-architecture

優點

但是,後端語言已經這麼多了,為什麼還要大費周章的將 JavaScript 移植到 Server 端呢?

這是因為 JavaScript 是一個事件驅動的語言,透過事件迴圈,能讓執行緒幾乎不會被卡住;而這樣的特性,非常適合用來接收高併發(High Concurrency)的請求。

例如在傳統的伺服器中,每個使用者的連接都會產生一個新的執行緒(看實作,不一定),並佔據一定的效能,伺服器在高併發的情況下,很容易就會由於應接不暇而無法服務新的流量;但 Node.js 會將每個 request 變成事件迴圈中待處理的事件,主執行緒只負責承接、轉拋、回應,並持續的在事件迴圈中循環,一切都以事件為核心在驅動程式運行,自然也就不會出現執行緒卡死的現象。

當然,如果是商業邏輯複雜的後端程式,效能瓶頸不在流量的服務,Node.js 就無用武之地;但在設計需要承接高流量,且處理邏輯不太複雜時,Node.js 可能就會是個可以考慮的選項。

功能

前面提到,Node.js 就是一個可以執行 JavaScript 的環境,而這個環境除了提供瀏覽器 Web API 實作的 setTimeoutsetIntervalconsole 之外,也因為執行環境不同,有另外一系列的 API 供開發者使用,例如可以讀寫檔案的 fs、處理網路請求的 http、做加解密雜湊處理的 crypto、設定叢集的 cluster 等等。

詳細的使用說明,可以參考 Node.js 的官網文件

事件迴圈

由於 JavaScript 擁有單執行緒的特性,且為了讓執行緒不會被需要等待的同步程式卡住,必須透過事件迴圈的機制來實現這個目標。如果各位讀者還有印象,我們在 這篇 有聊過瀏覽器中 JavaScript 的事件迴圈,其中有很大一部分是由瀏覽器完成的;在 Node.js 中則透過 libuv 來實現這部分的機制。不同於瀏覽器的事件迴圈,Node.js 中的事件迴圈大致會有以下幾個階段:

  • timers:執行 setTimeout setInterval 給的 callback
  • pending callbacks:執行被延遲到下一個事件迴圈的 I/O Callback
  • idle, prepare:Node.js 內部專用的階段
  • poll:檢索新的 I/O events,執行 I/O callbacks
  • check:執行 setImmediate 給的 callback。
  • close callbacks:執行關閉資源的 callback,例如 socket.on('close', ...)

相對於瀏覽器的事件迴圈多了好多個階段,但其實只是把所有的 callback 分成了四種:timers、I/O events、immediates、close handlers,並依照順序輪流執行,其他在概念上還是一樣的:每個階段有自己的 Queue,輪到它時清空 Queue,到下個階段,周而復始。

為避免主執行緒阻塞,poll 階段可以設定執行上限,到達上限時就會將 Queue 內的東西移交到 pending callbacks 階段的 Queue 中,下一個事件迴圈時再接續執行。

比較需要注意的地方是,微任務佇列(microtask queue)在每個階段結束後都會執行、清空,順序是先清空 process.nextTick 的 callback,再執行其他的如 Promise 的 callback。

常有人誤解 process.nextTick,會想問例如「一個 Tick 是多久?」之類的問題,但其實 Tick 指的就是事件迴圈中的一個階段,因此時間是不固定的喔!

結語

我們從最基本的介紹出發,認識了 Node.js 這個 Server 端的 JavaScript 執行環境,並提到 Node.js 的語言特性在高併發情況的優勢,最後重點理解 JavaScript 的重要特色:事件迴圈,背後是如何在伺服器端執行。

(本文作者是 ALPHA Camp 課程 學期四:業界專案實戰 的助教,前端工程師 Gary,擁有四年以上軟體開發經驗,現職為奧丁丁集團的開發工程師。本文轉載自前端三十系列文

參考資料

三分鐘小測驗,了解你該從哪開始自學JavaScript

成為企業渴求的程式人才!

在家學會 JavaScript 網路開發

全新「全端 Web App 開發」課程,給你看得見的學習成效!
超過 90% 轉職成功,400 位來自亞洲各國的 ALPHA Camp 校友,畢業後達成轉職、創業、出國工作的夢想!

探索「全端 Web App 開發」課程

給期待創新改變的你

前端x後端x全端 完整工程師技能樹

90% 學生轉職成功,職涯競爭力更上層樓
最專業的「全端 Web App 開發」課程,上班族邊工作也能同時培養第二專長!

加入 ALPHA Camp 學程式開發

學期一|程式設計入門

零基礎也學得會的程式入門課!

開始學帶得走的技能,為自己未來的成長鋪路

學期二|JavaScript 完整前端基礎

系統化學習 JavaScript

實作打好前端基礎,成為扎實的網頁開發者

11/19前報名學期一,搶先旁聽「電商專案線上Demo Day」
報名參加