nodejs開發指南
Node.js簡介
簡介:Node.js是一個為實時Web應用開發而誕生的平臺,從誕生之初就充分考慮了實時響應、超大規模數據要求下架構的擴展性。
特點:單線程、異步式I/O、事件驅動式的程序設計模型
部分實現遵循了CommomJS規范
-
Node.js能做什么:
- 具有復雜邏輯的網站
- 基于社交網絡的大規模Web應用
- Web Socket服務器
- TCP/UDP套接字應用程序
- 命令行工具
- 交互式終端程序
- 帶有圖形用戶界面的本地應用程序
- 單元測試工具
- 客戶端JavaScript編譯器
最大的特點就是采用異步式I/O與事件驅動的架構設計,使用單線程模型,對于所有I/O都采用異步式的請求方式,避免了頻繁的上下文切換
采用回調函數等待結果返回
Node.js的異步機制是基于事件的
-
弊端:
- 不符合開發者的常規線性思路,往往需要把一個完整的邏輯拆分為一個個事件,增加了開發和調試難度
阻塞:線程在執行過程中如果遇到磁盤讀寫或者網絡通信(統稱I/O操作),通常要耗費較長的事件,這時操作系統會剝奪這個線程的CPU控制權,使其暫停執行,同時將資源讓給其他的工作線程,這種線程調度方式成為阻塞
單線程事件驅動的異步式I/O比傳統的多線程阻塞式I/O好在少了多線程的開銷
同步式I/O(阻塞式) | 異步式I/O(非阻塞式) |
---|---|
利用多線程提供吞吐量 | 單線程即可實現高吞吐量 |
通過事件片分割和線程調度利用多核CPU | 通過功能劃分利用多核CPU |
需要由操作系統調度多線程使用多核CPU | 可以將單進程綁定到單核CPU |
難以充分利用CPU資源 | 可以充分利用CPU資源 |
內存軌跡大,數據局部性弱 | 內存軌跡小,數據局部性強 |
符合線性的編程思維 | 不符合傳統編程思維 |
Node.js不鼓勵使用同步I/O
Node.js程序由事件循環開始,到時間循環結束,所有的邏輯都是事件的回調函數
模塊(Module)和包(Package)是Node.js最重要的支柱
模塊是Node.js應用程序的基本組成部分,文件和模塊是一一對應的,一個Node.js文件就是一個模塊
包是在模塊基礎上更深一步的抽象
他將某個獨立的功能封裝起來,用于發布、更新、依賴管理和版本控制
-
包應該具備以下特征:
- package.json必須在包的頂層目錄下
- 二進制文件應該在bin目錄下
- Javascript代碼應該在lib目錄下
- 文檔應該在doc目錄下
- 單元測試應該在test目錄下
-
package.json字段:
- name : 包的名稱,必須是唯一的,由小寫英文字母、數字和下劃線組成,不能包含空格
- description : 包的簡要說明
- version : 符合語義化版本識別規范的版本字符串
- keywords : 關鍵字數組,通常用于搜索
- maintainers : 維護者數組,每個元素要包含name、email(可選)、web(可選)字段
- contributors : 貢獻者數組,格式與maintainers 相同。包的作者應該是貢獻者數組的第一個元素
- bugs : 提交bug的地址,可以是網址或者電子郵件地址
- licenses : 許可證數組,每個元素要包含type(許可證名稱)和url(連接到許可證文本的地址)
- repositories : 倉庫托管地址數組,每個元素要包含type(倉庫的類型,如git)、url(倉庫的地址)和path(相對于倉庫的路徑,可選)字段
- dependencies : 包的依賴,一個關聯數組,由包名稱和版本號組成
Node.js 核心模塊
- 全局對象
- 常用工具
- 事件機制
- 文件訪問系統
- HTTP服務器與客戶端
全局對象(global) : 它及所有屬性都可以在程序的任何地方訪問
-
全局變量 :
在最外層定義的變量
全局對象的屬性
-
隱式定義的變量(未定義直接賦值的變量)
tips :
永遠使用var定義變量以避免引入全局變量,因為全局變量會污染命名空間,提高代碼的耦合風險
- process : 用于描述當前Node.js進程狀態的對象,提供了一個與操作系統的簡單接口*
- process.argv : 命令行參數數組
- process.stdout : 標準輸出流
- process.stdin : 標準輸入流
- process.nextTick(callback) : 為事件循環設置一項任務
- console : 用于提供控制臺標準輸出
-
util : 提供常用函數的集合
- util.inherits(constructor, superConstructor) : 一個思想對象間原型繼承的函數
- util.inspect(object, [showHidden], [depth], [colors]) : 一個將任意對象轉換為字符串的方法,通常用于調試和錯誤輸出
-
events : 事件驅動
- events.EventEmitter : 事件發射與事件監聽器功能的封裝
- EventEmitter.on(event, listener) : 為指定事件注冊一個監聽器,接受一個字符串event和一個回調函數listener
- EventEmitter.emit(event, [arg1], [arg2], [...]) : 發射event事件,傳遞若干可選參數到事件監聽器的參數表
- EventEmitter.once(event, listener) : 為指定事件注冊一個單次監聽器,即監聽器最多只會觸發一次,觸發后立刻接觸該監聽器
- EventEmitter.removeListener(event, listener) : 移除指定事件的某個監聽器,listener必須是該事件已經注冊過的監聽器
- error事件
- 繼承EventEmitter : 大多數時候我們不會直接使用EventEmitter,而是在對象中繼承它。包括fs、net、http
- events.EventEmitter : 事件發射與事件監聽器功能的封裝
-
文件系統fs
- fs.readFile(filename, [encoding], [callback(err, data)])
- fs.readFileSync(filename, [encoding])
- fs.open(path, flags, [mode], [callback(err, fd)])
- fs.read(fd, buffer, offset, length, position, [callback(err, bytesRead, buffer)])
- 一般來說,除非必要,否則不要使用這種方式讀取文件
-
HTTP服務器與客戶端
- Node.js標準庫提供了http模塊,其中封裝了一個高效的HTTP服務器和一個簡易的HTTP客戶端
http.Server是http模塊中的HTTP服務器對象
-
http.Server的事件
- request : 當客戶端請求到來時,該事件觸發,提供兩個參數req和res,分別是http.ServerRequest和http.ServerResponse的實例,表示請求和響應信息
- connection : 當TCP連接建立時,該事件被觸發,提供一個參數socket,為net.Socket的實例
- close : 當服務器關閉時,該事件被觸發
-
http.ServerRequest : HTTP請求的信息
- data : 當請求體數據到來時,該事件被觸發。該事件提供一個參數chunk,表示接收到的數據
- end : 當請求體數據傳輸完成時,該事件被觸發,伺候不會再有數據到來
- close : 用戶當前請求結束時,該事件被觸發
-
http.ServerResponse : 返回給客戶端的信息
- response.writeHead(statusCode, [headers]) : 向請求的客戶端發送響應頭
- respinse.write(data, [encoding]) : 向請求的客戶端發送響應內容
- response.end([data], [encoding]) : 響應結束,告知客戶端所有發送已經完成
-
HTTP客戶端
- http模塊提供了
http.request
和http.get
,作為客戶端向HTTP服務器發起請求
-
http.request(options, callback),options :
- host : 請求網站的域名或IP地址
- port : 請求網站的端口,默認80
- method : 請求方法,默認GET
- path : 請求的相對于根的路徑,默認'/'
- headers : 一個關聯數組對象,為請求頭的內容
http.get(options, callback) : 簡化便方法處理GET請求
http.ClientRequest : 由
http.request
和http.get
返回產生的對象,表示一個已經產生且正在進行中的HTTP請求-
http.ClientResponse : 提供了三個事件
data
、end
和close
ClientResponse的屬性
名稱 含義 statusCode HTTP狀態碼,如200/404/500 httpVersion HTTP協議版本,通常是1.0或1.1 headers HTTP請求頭 trailers HTTP請求尾 response.setEncoding([encoding]) : 設置默認的編碼,當data事件被觸發時,數據將會以encoding編碼,默認值null
response.pause() : 暫停接收數據和發送事件。方便實現下載功能
response.resume() : 從暫停的狀態中恢復
- http模塊提供了
Node.js 開發
-
Web開發架構對比
特性 模板為中心架構 MVC架構 頁面產生方式 執行并替換標簽中的語句 由模板引擎生成HTML頁面 路徑解析 對應到文件系統 由控制器定義 數據訪問 通過SQL語句查詢或訪問文件系統 對象關系模型 架構中心 腳本語言是靜態HTTP服務器的擴展 靜態HTTP服務器是腳本語言的補充 適用范圍 小規模網站 大規模網站 學習難度 容易 較難 -
REST : 表征狀態轉移,他是一種基于HTTP協議的網絡應用的接口風格,充分利用HTTP的方法實現統一風格接口的服務
- GET : 請求獲取指定資源(常用,獲?。?/li>
- HEAD : 請求指定資源的響應頭
- POST : 向指定資源提交數據(常用,新增)
- PUT : 請求服務器存儲一個資源(常用,更新)
- DELETE : 請求服務器刪除指定資源(常用,刪除)
- TRACE : 回顯服務器收到的請求,主要用于測試或診斷
- CONNECT : HTTP/1.1協議中預留給能夠將連接改為管道方式的代理服務器
- OPTIONS : 返回服務器支持的HTTP請求方法
-
冪等 : 重復請求多次與一次請求的效果是一樣的
請求方式 安全 冪等 GET 是 是 POST 否 否 PUT 否 是 DELETE 否 是 - 安全 : 指沒有附作用,即請求不會對資源產生變動,連續多次訪問所獲得的結果不受訪問者影響
當你訪問任何被上面兩條同樣的規則匹配到的路徑時,會發現請求總是被前一條路由規則捕獲,后面的規則會被忽略,Express提供了路由控制權轉移的方法,即回調函數的第三個參數next
-
模板引擎 : 一個從頁面模板根據一定的規則生成HTML的工具
問題 :
- 頁面功能邏輯與頁面布局樣式耦合,網站規模變大以后逐漸難以維護
- 語法復雜,對于非技術的網頁設計者來說門檻較高,難以學習
- 功能過于全面,頁面設計者可以在頁面上編程,不利于功能劃分,也使模板解析效率降低
Node.js 進階
- 模塊加載機制
- 異步編程模式下的控制流
- Node.js 應用部署
- Node.js 的一些劣勢
- Node.js的模塊可以分為兩大類 : 核心模塊(fs、http、net、vm等),文件模塊(JS代碼、JSON等)
- Node.js不會被重復加載,這是因為Node.js通過文件名緩存所有加載過得文件模塊
- Node.js應用部署缺陷 :
- 不支持故障恢復
- 沒有日志
- 無法利用多核提高性能
- 獨占端口
- 需要手動啟動
- Node.js不適合做什么 :
- 計算密集型程序
- 單用戶多任務型應用
- 邏輯十分復雜的事務
- Unicode與國際化