nodejs開(kāi)發(fā)指南
Node.js簡(jiǎn)介
簡(jiǎn)介:Node.js是一個(gè)為實(shí)時(shí)Web應(yīng)用開(kāi)發(fā)而誕生的平臺(tái),從誕生之初就充分考慮了實(shí)時(shí)響應(yīng)舀寓、超大規(guī)模數(shù)據(jù)要求下架構(gòu)的擴(kuò)展性炒嘲。
特點(diǎn):?jiǎn)尉€(xiàn)程粪般、異步式I/O、事件驅(qū)動(dòng)式的程序設(shè)計(jì)模型
部分實(shí)現(xiàn)遵循了CommomJS規(guī)范
-
Node.js能做什么:
- 具有復(fù)雜邏輯的網(wǎng)站
- 基于社交網(wǎng)絡(luò)的大規(guī)模Web應(yīng)用
- Web Socket服務(wù)器
- TCP/UDP套接字應(yīng)用程序
- 命令行工具
- 交互式終端程序
- 帶有圖形用戶(hù)界面的本地應(yīng)用程序
- 單元測(cè)試工具
- 客戶(hù)端JavaScript編譯器
最大的特點(diǎn)就是采用異步式I/O與事件驅(qū)動(dòng)的架構(gòu)設(shè)計(jì)帕棉,使用單線(xiàn)程模型,對(duì)于所有I/O都采用異步式的請(qǐng)求方式饼记,避免了頻繁的上下文切換
采用回調(diào)函數(shù)等待結(jié)果返回
Node.js的異步機(jī)制是基于事件的
-
弊端:
- 不符合開(kāi)發(fā)者的常規(guī)線(xiàn)性思路香伴,往往需要把一個(gè)完整的邏輯拆分為一個(gè)個(gè)事件,增加了開(kāi)發(fā)和調(diào)試難度
阻塞:線(xiàn)程在執(zhí)行過(guò)程中如果遇到磁盤(pán)讀寫(xiě)或者網(wǎng)絡(luò)通信(統(tǒng)稱(chēng)I/O操作)具则,通常要耗費(fèi)較長(zhǎng)的事件即纲,這時(shí)操作系統(tǒng)會(huì)剝奪這個(gè)線(xiàn)程的CPU控制權(quán),使其暫停執(zhí)行博肋,同時(shí)將資源讓給其他的工作線(xiàn)程低斋,這種線(xiàn)程調(diào)度方式成為阻塞
單線(xiàn)程事件驅(qū)動(dòng)的異步式I/O比傳統(tǒng)的多線(xiàn)程阻塞式I/O好在少了多線(xiàn)程的開(kāi)銷(xiāo)
同步式I/O(阻塞式) | 異步式I/O(非阻塞式) |
---|---|
利用多線(xiàn)程提供吞吐量 | 單線(xiàn)程即可實(shí)現(xiàn)高吞吐量 |
通過(guò)事件片分割和線(xiàn)程調(diào)度利用多核CPU | 通過(guò)功能劃分利用多核CPU |
需要由操作系統(tǒng)調(diào)度多線(xiàn)程使用多核CPU | 可以將單進(jìn)程綁定到單核CPU |
難以充分利用CPU資源 | 可以充分利用CPU資源 |
內(nèi)存軌跡大,數(shù)據(jù)局部性弱 | 內(nèi)存軌跡小匪凡,數(shù)據(jù)局部性強(qiáng) |
符合線(xiàn)性的編程思維 | 不符合傳統(tǒng)編程思維 |
Node.js不鼓勵(lì)使用同步I/O
Node.js程序由事件循環(huán)開(kāi)始膊畴,到時(shí)間循環(huán)結(jié)束,所有的邏輯都是事件的回調(diào)函數(shù)
模塊(Module)和包(Package)是Node.js最重要的支柱
模塊是Node.js應(yīng)用程序的基本組成部分锹雏,文件和模塊是一一對(duì)應(yīng)的巴比,一個(gè)Node.js文件就是一個(gè)模塊
包是在模塊基礎(chǔ)上更深一步的抽象
他將某個(gè)獨(dú)立的功能封裝起來(lái),用于發(fā)布礁遵、更新轻绞、依賴(lài)管理和版本控制
-
包應(yīng)該具備以下特征:
- package.json必須在包的頂層目錄下
- 二進(jìn)制文件應(yīng)該在bin目錄下
- Javascript代碼應(yīng)該在lib目錄下
- 文檔應(yīng)該在doc目錄下
- 單元測(cè)試應(yīng)該在test目錄下
-
package.json字段:
- name : 包的名稱(chēng),必須是唯一的佣耐,由小寫(xiě)英文字母政勃、數(shù)字和下劃線(xiàn)組成,不能包含空格
- description : 包的簡(jiǎn)要說(shuō)明
- version : 符合語(yǔ)義化版本識(shí)別規(guī)范的版本字符串
- keywords : 關(guān)鍵字?jǐn)?shù)組兼砖,通常用于搜索
- maintainers : 維護(hù)者數(shù)組奸远,每個(gè)元素要包含name、email(可選)讽挟、web(可選)字段
- contributors : 貢獻(xiàn)者數(shù)組懒叛,格式與maintainers 相同。包的作者應(yīng)該是貢獻(xiàn)者數(shù)組的第一個(gè)元素
- bugs : 提交bug的地址耽梅,可以是網(wǎng)址或者電子郵件地址
- licenses : 許可證數(shù)組薛窥,每個(gè)元素要包含type(許可證名稱(chēng))和url(連接到許可證文本的地址)
- repositories : 倉(cāng)庫(kù)托管地址數(shù)組,每個(gè)元素要包含type(倉(cāng)庫(kù)的類(lèi)型,如git)诅迷、url(倉(cāng)庫(kù)的地址)和path(相對(duì)于倉(cāng)庫(kù)的路徑佩番,可選)字段
- dependencies : 包的依賴(lài),一個(gè)關(guān)聯(lián)數(shù)組罢杉,由包名稱(chēng)和版本號(hào)組成
Node.js 核心模塊
- 全局對(duì)象
- 常用工具
- 事件機(jī)制
- 文件訪(fǎng)問(wèn)系統(tǒng)
- HTTP服務(wù)器與客戶(hù)端
全局對(duì)象(global) : 它及所有屬性都可以在程序的任何地方訪(fǎng)問(wèn)
-
全局變量 :
在最外層定義的變量
全局對(duì)象的屬性
-
隱式定義的變量(未定義直接賦值的變量)
tips :
永遠(yuǎn)使用var定義變量以避免引入全局變量趟畏,因?yàn)槿肿兞繒?huì)污染命名空間,提高代碼的耦合風(fēng)險(xiǎn)
- process : 用于描述當(dāng)前Node.js進(jìn)程狀態(tài)的對(duì)象滩租,提供了一個(gè)與操作系統(tǒng)的簡(jiǎn)單接口*
- process.argv : 命令行參數(shù)數(shù)組
- process.stdout : 標(biāo)準(zhǔn)輸出流
- process.stdin : 標(biāo)準(zhǔn)輸入流
- process.nextTick(callback) : 為事件循環(huán)設(shè)置一項(xiàng)任務(wù)
- console : 用于提供控制臺(tái)標(biāo)準(zhǔn)輸出
-
util : 提供常用函數(shù)的集合
- util.inherits(constructor, superConstructor) : 一個(gè)思想對(duì)象間原型繼承的函數(shù)
- util.inspect(object, [showHidden], [depth], [colors]) : 一個(gè)將任意對(duì)象轉(zhuǎn)換為字符串的方法赋秀,通常用于調(diào)試和錯(cuò)誤輸出
-
events : 事件驅(qū)動(dòng)
- events.EventEmitter : 事件發(fā)射與事件監(jiān)聽(tīng)器功能的封裝
- EventEmitter.on(event, listener) : 為指定事件注冊(cè)一個(gè)監(jiān)聽(tīng)器,接受一個(gè)字符串event和一個(gè)回調(diào)函數(shù)listener
- EventEmitter.emit(event, [arg1], [arg2], [...]) : 發(fā)射event事件持际,傳遞若干可選參數(shù)到事件監(jiān)聽(tīng)器的參數(shù)表
- EventEmitter.once(event, listener) : 為指定事件注冊(cè)一個(gè)單次監(jiān)聽(tīng)器沃琅,即監(jiān)聽(tīng)器最多只會(huì)觸發(fā)一次,觸發(fā)后立刻接觸該監(jiān)聽(tīng)器
- EventEmitter.removeListener(event, listener) : 移除指定事件的某個(gè)監(jiān)聽(tīng)器蜘欲,listener必須是該事件已經(jīng)注冊(cè)過(guò)的監(jiān)聽(tīng)器
- error事件
- 繼承EventEmitter : 大多數(shù)時(shí)候我們不會(huì)直接使用EventEmitter益眉,而是在對(duì)象中繼承它。包括fs姥份、net郭脂、http
- events.EventEmitter : 事件發(fā)射與事件監(jiān)聽(tīng)器功能的封裝
-
文件系統(tǒng)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)])
- 一般來(lái)說(shuō),除非必要澈歉,否則不要使用這種方式讀取文件
-
HTTP服務(wù)器與客戶(hù)端
- Node.js標(biāo)準(zhǔn)庫(kù)提供了http模塊展鸡,其中封裝了一個(gè)高效的HTTP服務(wù)器和一個(gè)簡(jiǎn)易的HTTP客戶(hù)端
http.Server是http模塊中的HTTP服務(wù)器對(duì)象
-
http.Server的事件
- request : 當(dāng)客戶(hù)端請(qǐng)求到來(lái)時(shí),該事件觸發(fā)埃难,提供兩個(gè)參數(shù)req和res莹弊,分別是http.ServerRequest和http.ServerResponse的實(shí)例,表示請(qǐng)求和響應(yīng)信息
- connection : 當(dāng)TCP連接建立時(shí)涡尘,該事件被觸發(fā)忍弛,提供一個(gè)參數(shù)socket,為net.Socket的實(shí)例
- close : 當(dāng)服務(wù)器關(guān)閉時(shí)考抄,該事件被觸發(fā)
-
http.ServerRequest : HTTP請(qǐng)求的信息
- data : 當(dāng)請(qǐng)求體數(shù)據(jù)到來(lái)時(shí)细疚,該事件被觸發(fā)。該事件提供一個(gè)參數(shù)chunk川梅,表示接收到的數(shù)據(jù)
- end : 當(dāng)請(qǐng)求體數(shù)據(jù)傳輸完成時(shí)疯兼,該事件被觸發(fā),伺候不會(huì)再有數(shù)據(jù)到來(lái)
- close : 用戶(hù)當(dāng)前請(qǐng)求結(jié)束時(shí)贫途,該事件被觸發(fā)
-
http.ServerResponse : 返回給客戶(hù)端的信息
- response.writeHead(statusCode, [headers]) : 向請(qǐng)求的客戶(hù)端發(fā)送響應(yīng)頭
- respinse.write(data, [encoding]) : 向請(qǐng)求的客戶(hù)端發(fā)送響應(yīng)內(nèi)容
- response.end([data], [encoding]) : 響應(yīng)結(jié)束吧彪,告知客戶(hù)端所有發(fā)送已經(jīng)完成
-
HTTP客戶(hù)端
- http模塊提供了
http.request
和http.get
,作為客戶(hù)端向HTTP服務(wù)器發(fā)起請(qǐng)求
-
http.request(options, callback)丢早,options :
- host : 請(qǐng)求網(wǎng)站的域名或IP地址
- port : 請(qǐng)求網(wǎng)站的端口来氧,默認(rèn)80
- method : 請(qǐng)求方法,默認(rèn)GET
- path : 請(qǐng)求的相對(duì)于根的路徑,默認(rèn)'/'
- headers : 一個(gè)關(guān)聯(lián)數(shù)組對(duì)象啦扬,為請(qǐng)求頭的內(nèi)容
http.get(options, callback) : 簡(jiǎn)化便方法處理GET請(qǐng)求
http.ClientRequest : 由
http.request
和http.get
返回產(chǎn)生的對(duì)象,表示一個(gè)已經(jīng)產(chǎn)生且正在進(jìn)行中的HTTP請(qǐng)求-
http.ClientResponse : 提供了三個(gè)事件
data
凫碌、end
和close
ClientResponse的屬性
名稱(chēng) 含義 statusCode HTTP狀態(tài)碼扑毡,如200/404/500 httpVersion HTTP協(xié)議版本,通常是1.0或1.1 headers HTTP請(qǐng)求頭 trailers HTTP請(qǐng)求尾 response.setEncoding([encoding]) : 設(shè)置默認(rèn)的編碼盛险,當(dāng)data事件被觸發(fā)時(shí)瞄摊,數(shù)據(jù)將會(huì)以encoding編碼,默認(rèn)值null
response.pause() : 暫停接收數(shù)據(jù)和發(fā)送事件苦掘。方便實(shí)現(xiàn)下載功能
response.resume() : 從暫停的狀態(tài)中恢復(fù)
- http模塊提供了
Node.js 開(kāi)發(fā)
-
Web開(kāi)發(fā)架構(gòu)對(duì)比
特性 模板為中心架構(gòu) MVC架構(gòu) 頁(yè)面產(chǎn)生方式 執(zhí)行并替換標(biāo)簽中的語(yǔ)句 由模板引擎生成HTML頁(yè)面 路徑解析 對(duì)應(yīng)到文件系統(tǒng) 由控制器定義 數(shù)據(jù)訪(fǎng)問(wèn) 通過(guò)SQL語(yǔ)句查詢(xún)或訪(fǎng)問(wèn)文件系統(tǒng) 對(duì)象關(guān)系模型 架構(gòu)中心 腳本語(yǔ)言是靜態(tài)HTTP服務(wù)器的擴(kuò)展 靜態(tài)HTTP服務(wù)器是腳本語(yǔ)言的補(bǔ)充 適用范圍 小規(guī)模網(wǎng)站 大規(guī)模網(wǎng)站 學(xué)習(xí)難度 容易 較難 -
REST : 表征狀態(tài)轉(zhuǎn)移换帜,他是一種基于HTTP協(xié)議的網(wǎng)絡(luò)應(yīng)用的接口風(fēng)格,充分利用HTTP的方法實(shí)現(xiàn)統(tǒng)一風(fēng)格接口的服務(wù)
- GET : 請(qǐng)求獲取指定資源(常用鹤啡,獲裙咄铡)
- HEAD : 請(qǐng)求指定資源的響應(yīng)頭
- POST : 向指定資源提交數(shù)據(jù)(常用,新增)
- PUT : 請(qǐng)求服務(wù)器存儲(chǔ)一個(gè)資源(常用递瑰,更新)
- DELETE : 請(qǐng)求服務(wù)器刪除指定資源(常用祟牲,刪除)
- TRACE : 回顯服務(wù)器收到的請(qǐng)求,主要用于測(cè)試或診斷
- CONNECT : HTTP/1.1協(xié)議中預(yù)留給能夠?qū)⑦B接改為管道方式的代理服務(wù)器
- OPTIONS : 返回服務(wù)器支持的HTTP請(qǐng)求方法
-
冪等 : 重復(fù)請(qǐng)求多次與一次請(qǐng)求的效果是一樣的
請(qǐng)求方式 安全 冪等 GET 是 是 POST 否 否 PUT 否 是 DELETE 否 是 - 安全 : 指沒(méi)有附作用抖部,即請(qǐng)求不會(huì)對(duì)資源產(chǎn)生變動(dòng)说贝,連續(xù)多次訪(fǎng)問(wèn)所獲得的結(jié)果不受訪(fǎng)問(wèn)者影響
當(dāng)你訪(fǎng)問(wèn)任何被上面兩條同樣的規(guī)則匹配到的路徑時(shí),會(huì)發(fā)現(xiàn)請(qǐng)求總是被前一條路由規(guī)則捕獲慎颗,后面的規(guī)則會(huì)被忽略乡恕,Express提供了路由控制權(quán)轉(zhuǎn)移的方法,即回調(diào)函數(shù)的第三個(gè)參數(shù)next
-
模板引擎 : 一個(gè)從頁(yè)面模板根據(jù)一定的規(guī)則生成HTML的工具
問(wèn)題 :
- 頁(yè)面功能邏輯與頁(yè)面布局樣式耦合俯萎,網(wǎng)站規(guī)模變大以后逐漸難以維護(hù)
- 語(yǔ)法復(fù)雜傲宜,對(duì)于非技術(shù)的網(wǎng)頁(yè)設(shè)計(jì)者來(lái)說(shuō)門(mén)檻較高,難以學(xué)習(xí)
- 功能過(guò)于全面讯屈,頁(yè)面設(shè)計(jì)者可以在頁(yè)面上編程蛋哭,不利于功能劃分,也使模板解析效率降低
Node.js 進(jìn)階
- 模塊加載機(jī)制
- 異步編程模式下的控制流
- Node.js 應(yīng)用部署
- Node.js 的一些劣勢(shì)
- Node.js的模塊可以分為兩大類(lèi) : 核心模塊(fs涮母、http谆趾、net、vm等)叛本,文件模塊(JS代碼沪蓬、JSON等)
- Node.js不會(huì)被重復(fù)加載,這是因?yàn)镹ode.js通過(guò)文件名緩存所有加載過(guò)得文件模塊
- Node.js應(yīng)用部署缺陷 :
- 不支持故障恢復(fù)
- 沒(méi)有日志
- 無(wú)法利用多核提高性能
- 獨(dú)占端口
- 需要手動(dòng)啟動(dòng)
- Node.js不適合做什么 :
- 計(jì)算密集型程序
- 單用戶(hù)多任務(wù)型應(yīng)用
- 邏輯十分復(fù)雜的事務(wù)
- Unicode與國(guó)際化