1.什么是 Node.js
Node.js是一個(gè)JavaScript運(yùn)行平臺(tái), 使用 Google V8引擎(基于es6). 特征是異步和事件驅(qū)動(dòng)機(jī)制。Node.js是單線程編程模型,可以規(guī)避一些在線程編程中出現(xiàn)的問(wèn)題,如資源死鎖和競(jìng)態(tài)條件
2.非阻塞I/O
在執(zhí)行磁盤(pán)或網(wǎng)絡(luò)這樣的慢I/O操作時(shí),我們希望程序可以繼續(xù)執(zhí)行其他業(yè)務(wù)邏輯。Node用三種技術(shù)來(lái)實(shí)現(xiàn): 事件、異步API、非阻塞I/O。
為了更好的解釋非阻塞I/O, 引用一下Node.js實(shí)戰(zhàn)(第二版)
在Node程序員看來(lái),非阻塞I/O是個(gè)底層屬于。它的意思是說(shuō),你的程序可以在做其他事情時(shí),發(fā)起一個(gè)請(qǐng)求來(lái)獲取網(wǎng)絡(luò)資源,然后當(dāng)網(wǎng)絡(luò)操作完成時(shí),將會(huì)運(yùn)行一個(gè)回調(diào)函數(shù)來(lái)處理這個(gè)操作的結(jié)果。
結(jié)合 jawil的github issue
看看這樣的業(yè)務(wù)場(chǎng)景:需要從多個(gè)數(shù)據(jù)源拉取數(shù)據(jù),然后進(jìn)行處理。
①串行獲取數(shù)據(jù),這是我們一般的解決方案,一PHP為例的I/O阻塞-PHP為例,假如獲取profile和timeline操作各需要1s,那么串行獲取就需要2s。
②Node.js非阻塞I/O事件會(huì)創(chuàng)建一個(gè)線程去執(zhí)行,然后主線程會(huì)繼續(xù)往下執(zhí)行,因此,拿profile的動(dòng)作觸發(fā)一個(gè)I/O事件,馬上就會(huì)去執(zhí)行拿timeline的動(dòng)作,兩個(gè)動(dòng)作并行執(zhí)行,加入各需要1s,那么總的時(shí)間就是1s。它們的I/O操作執(zhí)行完成后,會(huì)發(fā)射一個(gè)事件,profile和timeline,事件代理接收后繼續(xù)往下執(zhí)行后面的邏輯,這就是Node.js非阻塞I/O的特點(diǎn)。
非阻塞I/O是程序執(zhí)行過(guò)程中,I/O操作不會(huì)阻塞程序的執(zhí)行,也就是在I/O操作的同時(shí),繼續(xù)執(zhí)行其他代碼(這得益于Node的事件循環(huán)機(jī)制)。在I/O設(shè)備效率還遠(yuǎn)遠(yuǎn)低于CPU效率的時(shí)代,這種I/O模型(非阻塞I/O)為程序帶來(lái)的性能上的提高是非??捎^的。
libuv是提供快速、跨平臺(tái)、非阻塞I/O的本地庫(kù)
3. 核心模塊
Node的標(biāo)注庫(kù)核很精巧,是在JavaScript標(biāo)準(zhǔn)上加入了文件和TCP/IP網(wǎng)絡(luò)功能,使其成為一個(gè)可以編寫(xiě)服務(wù)器端的編程語(yǔ)言。常用node庫(kù), 文件系統(tǒng)庫(kù)(fs, path)、TCP客戶端和服務(wù)端庫(kù)(net)、HTTP庫(kù)(http和https)、域名解析庫(kù)(dns)、用于寫(xiě)測(cè)試的斷言庫(kù)(assert)、用于查詢(xún)平臺(tái)信息的操作系統(tǒng)庫(kù)(os)、用于處理事件的事件模塊。
4. Node自帶工具
Node自帶npm包管理器以及調(diào)試器
- npm要求node根目錄下有一個(gè)package.json文件, 創(chuàng)建這個(gè)文件的命令
npm init -y
- node調(diào)試器支持單步執(zhí)行和REPL(讀取-計(jì)算-輸出-循環(huán))
啟動(dòng)調(diào)試的命令是
node debug xxx.js
5. v8引擎
v8引擎由Google的Chromium項(xiàng)目組開(kāi)發(fā),主要負(fù)責(zé)JavaScript代碼的解釋和執(zhí)行。它的特性是將JavaScript直接編譯為機(jī)器碼并對(duì)代碼進(jìn)行優(yōu)化,讓Node運(yùn)行的更快。