【入門指南】node.js

node.js簡介

  • node.js不是一種獨立語言,是一個可讓js在服務器端運行的平臺
  • 區別與傳統語言平臺依靠多線程來實現高併發的設計思路,node採用單線程、異步式I/O、事件驅動式的程序設計模型
  • node.js使用的JavaScript引擎爲V8引擎,還使用了高效的 libev 和 libeio 庫支持事件驅動和異步式 I/O 來代替傳統平臺的多線程模式,帶來性能的提高(傳統多線程模式對於 高併發的訪問,一方面線程長期阻塞等待,另外一方面爲了應付新請求而不斷增長線程,所以 會浪費大量系統資源,同時線程的增多也會佔用大量的 CPU 時間來處理內存上下文切換, 並且還容易遭受低速鏈接攻擊。)
  • 有別於php等語言,在使用php構建web服務時,必須外部依賴一個Nginx、Apache等http服務器,而後經過http服務區的模塊加載或CGI調用,才能將php的執行結果呈現給用戶;而node.js內置了http服務器模塊,無需再額外搭建
  • node.js能夠調用c/c++代碼,對於性能要求比較高的模塊可使用c/c++來實現

node.js只在第一次運行時會讀取文件內容,之後都會直接訪問內存,也就是當文件實時改動時,不會觸發從新編譯文件內容,因此須要使用supervisor、pm2等工具,對node服務進行實時管理php

異步式I/O 與事件驅動式編程

阻塞與線程

什麼是阻塞(block)呢?線程在執行中若是遇到磁盤讀寫或網絡通訊(統稱爲 I/O 操做), 一般要耗費較長的時間,這時操做系統會剝奪這個線程的 CPU 控制權,使其暫停執行,同 時將資源讓給其餘的工做線程,這種線程調度方式稱爲 阻塞。當 I/O 操做完畢時,操做系統 將這個線程的阻塞狀態解除,恢復其對CPU的控制權,令其繼續執行。這種 I/O 模式就是通 常的同步式 I/O(Synchronous I/O)或阻塞式 I/O (Blocking I/O)node

異步式 I/O (Asynchronous I/O)或非阻塞式 I/O (Non-blocking I/O)則針對 全部 I/O 操做不採用阻塞的策略。當線程遇到 I/O 操做時,不會以阻塞的方式等待 I/O 操做 的完成或數據的返回,而只是將 I/O 請求發送給操做系統,繼續執行下一條語句。當操做 系統完成 I/O 操做時,以事件的形式通知執行 I/O 操做的線程,線程會在特定時候處理這個 事件。爲了處理異步 I/O,線程必須有事件循環,不斷地檢查有沒有未處理的事件,依次予 以處理。c++

多線程與單線程的比較:

對於須要長時間計算的I/O處理操做web

  • 多線程模式:若是想實現高併發,就必須開啓多個線程 shell

  • 單線程模式:I/O異步,經過事件方式通知線程,便可完成高併發 express

單線程事件驅動的異步式 I/O 比傳統的多線程阻塞式 I/O 究竟好在哪裏呢?npm

  • 簡而言之, 異步式 I/O 就是少了多線程的開銷。對操做系統來講,建立一個線程的代價是十分昂貴的, 須要給它分配內存、列入調度,同時在線程切換的時候還要執行內存換頁,CPU 的緩存被 清空,切換回來的時候還要從新從內存中讀取信息,破壞了數據的局部性。(基於多線程的模型也有相應的解決方案,如輕量級線程(lightweight thread)等。事件驅動的單線程異步模型與多線 程同步模型到底誰更好是一件很是有爭議的事情,由於儘管消耗資源,後者的吞吐率並不比前者低)
  • 異步式編程的缺點在於不符合人們通常的程序設計思惟,存在回調地獄的狀況(使用async、promise等編寫方式)

node.js的事件循環機制

Node.js 程序由事件循環開始,到事件循環結束,全部的邏輯都是事件的回調函數,因此 Node.js 始終在事件循環中,程序入口就是 事件循環第一個事件的回調函數。事件的回調函數在執行的過程當中,可能會發出 I/O 請求或 直接發射(emit)事件,執行完畢後再返回事件循環,事件循環會檢查事件隊列中有沒有未 處理的事件,直到程序結束.編程

與其餘語言不一樣的是,Node.js 沒有顯式的事件循環,相似 Ruby 的 EventMachine::run() 的函數在 Node.js中是不存在的。Node.js的事件循環對開發者不可見,由libev庫實現。libev支持多種類型的事件,如 ev_io、ev_timer、ev_signal、ev_idle 等,在 Node.js 中均被 EventEmitter 封裝。libev 事件循環的每一次迭代,在 Node.js 中就是一次 Tick,libev 不 斷檢查是否有活動的、可供檢測的事件監聽器,直到檢測不到時才退出事件循環,進程結束json

npm包管理器

建立npm包

Node.js 根 據 CommonJS 規範實現了包機制,開發了 npm來解決包的發佈和獲取需求。 使用以下命令初始化建立npm包數組

npm init
複製代碼

Node.js 的包是一個目錄,其中包含一個 JSON 格式的包說明文件 package.json。嚴格符 合 CommonJS 規範的包應該具有如下特徵:

  • package.json 必須在包的頂層目錄下;
    • 做爲npm包的描述性文件,其中經常使用的字段:
    • main:做爲包模塊的入口(Node.js 在調用某個包時,會首先檢查包中 package.json 文件的 main 字段,將其做爲包的接口模塊,若是 package.json 或 main 字段不存在,會嘗試尋找 index.js 或 index.node 做 爲包的接口)
    • name:包的名稱
    • description:包的簡要說明
    • version:版本字符串
    • keywords:關鍵字數組,一般用於搜索
    • maintainers:維護者數組,每一個元素要包含 name、email (可選)、web (可選)字段
    • contributors:貢獻者數組,格式與maintainers相同。包的做者應該是貢獻者數組的第一個元素
    • bugs:提交bug的地址,能夠是網址或者電子郵件地址
    • licenses:許可證數組
    • repositories:倉庫託管地址數組
    • dependencies:包的依賴,一個關聯數組,由包名稱和版本號組成
  • 二進制文件應該在 bin 目錄下;
  • JavaScript 代碼應該在 lib 目錄下;
  • 文檔應該在 doc 目錄下;
  • 單元測試應該在 test 目錄下。 Node.js 對包的要求並無這麼嚴格,只要頂層目錄下有 package.json,並符合一些規範 便可。固然爲了提升兼容性,咱們仍是建議你在製做包的時候,嚴格遵照 CommonJS 規範

本地模式與全局模式

全局模式的安裝:

npm [install/i] -g [package_name]

爲何要使用全局模式呢?多數時候並非由於許多程序都有可能用到它,爲了減小多 重副本而使用全局模式,而是由於本地模式不會註冊 PATH 環境變量。舉例說明,咱們安裝 supervisor 是爲了在命令行中運行它,譬如直接運行 supervisor script.js,這時就須要在 PATH 環境變量中註冊 supervisor。npm 本地模式僅僅是把包安裝到 node_modules 子目錄下,其中 的 bin 目錄沒有包含在 PATH 環境變量中,不能直接在命令行中調用。而當咱們使用全局模 式安裝時,npm 會將包安裝到系統目錄,譬如 /usr/local/lib/node_modules/,同時 package.json 文 件中 bin 字段包含的文件會被連接到 /usr/local/bin/。/usr/local/bin/ 是在PATH 環境變量中默認 定義的,所以就能夠直接在命令行中運行 supervisor script.js命令了

使用全局模式安裝的包並不能直接在 JavaScript 文件中用 require 獲 得,由於 require 不會搜索 /usr/local/lib/node_modules/

區別:

  • 當咱們要把某個包做爲工程運行時的一部分時,經過本地模式獲取
  • 若是要 在命令行下使用,則使用全局模式安裝

建立全局連接

npm 提供了一個有趣的命令 npm link,它的功能是在本地包和全局包之間建立符號鏈 接。咱們說過使用全局模式安裝的包不能直接經過 require 使用,但經過 npm link命令 能夠打破這一限制。舉個例子,咱們已經經過 npm install -g express 安裝了 express, 5 這時在工程的目錄下運行命令: npm link express ./node_modules/express -> /usr/local/lib/node_modules/express 咱們能夠在 node_modules 子目錄中發現一個指向安裝到全局的包的符號連接。經過這種方法,咱們就能夠把全局包當本地包來使用了

除了將全局的包連接到本地之外,使用 npm link命令還能夠將本地的包連接到全局。 使用方法是在包目錄( package.json 所在目錄)中運行 npm link 命令。若是咱們要開發 一個包,利用這種方法能夠很是方便地在不一樣的工程間進行調試和測試

具體使用案例:

如今有兩個模塊,npm-link-module爲咱們開發的npm包;npm-link-test爲咱們要使用上面的npm包來作測試

cd npm-link-module  //進入開發的npm包目錄裏
npm link //將本地的包連接到全局

cd npm-link-test  //進入到測試項目中
npm link npm-link-module  //將全局包npm-link-module 連接到本地node_modules路徑下,這樣本地就可使用require()引用了
複製代碼

包的發佈

  • npm adduser 建立帳號
  • npm whoami 命令測驗是否已經取得了帳號
  • npm publish 發佈包
  • 經過https://www.npmjs.com/ 去搜索本身發佈的包
  • 往後有更新時,更改package.json中的version版本,從新npm publish便可
  • npm unpublish 取消已發佈的包

node命令行調試(調試功能由 V8 提供)

使用node debug xxx.js 便可開啓調試模式

相關文章
相關標籤/搜索