Node.js 系列 - 基礎概念

做爲還在漫漫前端學習路上的一位自學者。我以學習分享的方式來整理本身對於知識的理解,同時也但願可以給你們做爲一份參考。但願可以和你們共同進步,若有任何紕漏的話,但願你們多多指正。感謝萬分!前端


在 Node.js 系列的第一節裏, 我會先介紹 Node.js 的一些基本概念. 讓你在看完這篇文章時, 能對 "什麼是 Node.js?", "爲何用 Node.js?" 這兩個問題有個基本的概念. 而且嘗試寫下第一句 Node.js 代碼.node

什麼是 Node.js?

先來看看 Node 官網 給的答案:git

Node.js 是一個基於 Chrome V8 引擎的 JavaScript 運行環境。 Node.js 使用了一個事件驅動、非阻塞式 I/O 的模型,使其輕量又高效。程序員

基本上, 不少人第一次看到上面這段定義的時候, 徹底搞不懂它在說什麼...github

下面我就來逐步解釋 Node.js 的這段定義.數據庫

基於 Chrome V8 引擎的 JavaScript 運行環境

看到這句話後, 你可能第一個疑問是 🤔 "什麼是 Chrome V8 引擎?"瀏覽器

在解答這個問題以前, 回到咱們熟悉的前端領域, 我先問另外一個問題 🤔 "JavaScript 代碼是如何在瀏覽器中運行的?"服務器

簡單來講, 咱們所寫的 JavaScript 源代碼, 是爲了給人看的, 瀏覽器加載 JavaScript 代碼後, 它是看不懂的, 須要翻譯成機器碼, 也就是 "機器的語言", 纔可讓機器執行. 在瀏覽器中, JavaScript 引擎負責進行代碼的解釋. V8 引擎是 Chrome 瀏覽器在用的 JavaScript 引擎. V8 引擎由 C++ 實現, 支持跨平臺, 就是說能夠在各類操做系統上使用, Node.js 基於 V8 引擎, 意味着它可讓 JavaScript 代碼脫離瀏覽器的束縛, 在各類各樣不一樣的操做系統上運行.微信

那麼一句話總結, Node.js 不是一門語言, 是一個能夠讓 JavaScript 代碼在各類各樣的平臺上獲得執行的運行環境. 之因此支持 JavaScript 語法是由於基於 V8 引擎.網絡

非阻塞式 I/O

"非阻塞式 I/O", 我知道這幾個字看起來讓人有點懵. 彆着急, 那讓我換個說法, "不會阻塞 JavaScript 程序執行的 Input/Output 操做", 這樣會不會清楚一點? 可能你仍是不太懂, 那下面我就逐字地解釋.

在說 "非阻塞" 以前, 先了解什麼是 "阻塞". 從字面上理解, "阻塞" 就是堵住了, 通不過的意思. 在計算機中, 程序在線程內按順序被執行, 後面的操做必須等前面的操做結束才能被執行. 若是前一個操做耗時很長, 後面的操做就要一直等着, 直到前面的操做完成. 這個等待的狀態, 叫作 "阻塞".

線程: 程序執行流的最小單元。程序代碼在其中被 CPU 依次處理. 在一條線程中, 同一時間, 只有一段代碼被被執行, 或等待被執行.

如今再來講說什麼是 "Input/Output 操做". 從字面上翻譯就是 "輸入/輸出", 那輸的是什麼呢? 簡單說就是 "信息". 在程序執行過程當中若是須要操做系統進行 磁盤讀寫 或 網絡通訊, 咱們就都統稱爲 "I/O 操做". 例如, 從服務器獲取頁面, 寫入文件, 提交表單, 讀取數據庫都是屬於這個範疇的. 凡是這一類操做, 直觀感覺是 "花的時間較長". 那麼在代碼執行 I/O 操做時, 每每要讓後面的操做等很長時間. 整條線程一直處於阻塞的狀態, 這種 I/O 操做方式稱爲 "阻塞式 I/O". 拿生活舉例, 遊戲沒下載完, 我就只能乾等着玩不了.

在程序設計中, 對於高併發的任務 (同時發生的任務) , 在線程阻塞的狀況下, 整條線程不能執行程序, 這會致使任務處理速度極慢. 常見的方案是經過多線程來解決. 但每條線程的利用率並無增長, 同時也會致使硬件成本高昂.

併發: 在同一個時間段中, 幾個任務同時進行. 可是在任意時間點, 有且只有一個任務在執行.

(能夠想象成你在同時寫五份做業, 每份只寫幾筆就換下一個, 而後再反回來接着寫兩筆. 雖然五份做業在一段時間內同時都被寫了, 可是在任一時間點你只是在寫其中的一份做業.)

Screen Shot 2018-10-13 at 5.55.43 PM

在 Node.js 中, JavaScript 代碼在一個單一的主線程中進行處理, 同一時間只能處理一項任務. 爲了處理高併發, 採用了 "非阻塞式 I/O", 也能夠稱爲 "異步式 I/O". 當線程遇到 I/O 操做時,不會以阻塞的方式去等待操做完成. 而是將 I/O 操做先放到另外一個地方等待處理, 而後 Node.js 繼續執行下一條代碼. 等主線程代碼所有執行完畢後, 再去處理 I/O 操做. 具體的過程, 在下一段介紹.

事件驅動

繼續上一段的內容. 在 Node.js 中, 當主線程遇到 I/O 操做時,會先把 I/O 操做封裝成一個請求對象, 而後被推入到線程池中等待執行. 而後異步調用的第一階段結束, JavaScript 主線程繼續執行後續操做, 直至全部非阻塞操做都處理完. 由於 I/O 操做在線程池中等處處理, 因此也不會阻塞主線程.

當線程池有空餘線程時, 等待的 I/O 操做會被處理. 當 I/O 操做完成, 獲取的結果保存在請求對象的 result 屬性上. 操做系統會來檢查線程池是否有處理完的請求, 若是有, 就把請求對象加入到事件隊列中.

在主線程的全部非阻塞代碼都處理完後, 事件循環開始逐個處理事件隊列中的事件. 保存在請求對象的 result 屬性被取出, 做爲與請求綁定的回調函數的參數. 而後執行回調來完成此 I/O 操做.

當隊列中已經沒有未處理的事件了, 程序結束. 能夠看出程序的結束與否, 取決於事件是否被所有處理完畢, 所以稱 Node 是事件驅動的.

Screen Shot 2018-10-13 at 5.54.42 PM

作個比喻

若是很差理解的話, 能夠想象老王一我的去釣魚.

  • 單線程阻塞式 I/O 』就像老王把魚竿架好以後, 就在旁邊等着, 等魚漂抖動的時候就拉桿. 在等待的這段時間裏, 他是什麼也不幹的. 當前一條魚上鉤後, 老王才能釣下一條魚, 或者作其餘事情.
  • 多線程阻塞式 I/O 』過了幾天, 老王以爲這樣效率低, 就買了十把魚竿同時架起來. 在同一段時間內, 這種方法釣的魚的確多了, 但老王在一個時間點只能去操縱一個魚竿, 單個魚竿的效率很低, 老王仍舊一直守在魚竿旁, 在等的時候不能作其餘的事. 
  • 非阻塞式 I/O 』又過了幾天, 老王一個發明家朋友給了他一個 "自動通知魚竿", 魚上鉤後, 魚竿會給老王發微信通知他過來收魚. 這樣老王就能夠在等魚上鉤的時間裏去幹別的事情了.

爲何用 Node.js?

先來講 Node.js 的優勢:

  • 跨平臺性: Node.js 基於 V8 引擎, 使得其能夠覆蓋到平常所能見的大多數平臺.
  • 適合 "數據密集型實時應用": Node.js 採用非阻塞式 I/O 模型, 很是適用於處理涉及大量 I/O 操做的數據密集型應用. 好比, 聊天室, Web 服務器等.
  • "前端開發者" 學習成本低: Node.js 使用 JavaScript 語法, 對於前端開發人員來講, 學習成本很是低.
  • "第三方模塊" 豐富: 繁榮的 Node.js 社區 提供了豐富的第三方模塊供其使用. 經過這些模塊, Node.js 能夠擁有更多的應用場景.

固然 Node.js 也是有缺點的:

  • 不適合 "CPU 密集型應用": Node.js 不適合處理涉及大量 CPU 計算的任務. 好比, 視頻編碼、人工智能等.
  • 不能充分的利用多核 CPU 服務器: Node.js 是單線程的, 在多核設備上運行, 不能充分利用其性能. 可是 Node.js 其實也提供了支持多線程的方法.

安裝 Node.js

根據計算機平臺的不一樣, 安裝方法也略有差別. 本文側重於概念, 具體實操, 可能每位讀者因偏好不一樣, 方法各異. 在此就再也不贅述了.

最方便的方式是直接上官網去下載對應平臺的源碼或安裝包, 或者經過包管理器直接安裝.


Node.js 代碼實例

var http = require('http');

function myNodeServer(req, res){
    res.writeHead(200, {'Content-type':'text/plain'});
    res.write('Hello World'); 
    res.end();
}

http.createServer(myNodeServer).listen(3000); //監聽 3000 端口

console.log('Server is running!'); 
複製代碼

建立一個空文件, 把上面代碼複製到其中, 文件後綴改爲 .js. 而後在命令行中, 用 node 命令執行剛剛的文件 ( 注意文件所在目錄位置和文件名 ) .

Screen Shot 2018-10-13 at 5.53.27 PM

若是運行成功你的命令行上會顯示 "Server is running!" 這段話. 而後用瀏覽器訪問 http://localhost:3000/ 這個地址. 你會看到網頁上顯示 "Hello World". 至此你就實現了一個簡易 HTTP 服務器.

Screen Shot 2018-10-13 at 5.53.03 PM


Node.js 學習資源推薦


😆 好啦,今天的分享就告一段落啦。下一篇中,我會介紹 Node.js 的模塊機制。

傳送門 - Node.js 系列 - 模塊機制

若是喜歡的話就點個關注吧!O(∩_∩)O 謝謝各位的支持❗️

相關文章
相關標籤/搜索