前言
本系列為學(xué)習(xí)筆記竿屹。
是從菜鳥教程上學(xué)的。
NodeJS
簡(jiǎn)單的說 NodeJS就是運(yùn)行在服務(wù)器端的JavaScript伙单。
Node.js 是一個(gè)基于Chrome JavaScript 運(yùn)行時(shí)建立的一個(gè)平臺(tái)胯杭。
Node.js是一個(gè)事件驅(qū)動(dòng)的I/O服務(wù)端JavaScript環(huán)境,基于Goole的V8引擎膜宋,V8引擎執(zhí)行JavaScript的速度非沉蓿快,性能非常好秋茫。
安裝配置
本安裝教程已Node.js v4.4.3 LTS 版本為例
Node.js安裝包及源碼下載地址為:https://nodejs.org/en/download/史简。
你可以根據(jù)自不同的平臺(tái)選你需要的Node.js安裝包。
注:Linux 上安裝Node.js 需要安裝Python 2.6或2.7肛著,不建議安裝Python 3.0 以上版本
Window 上安裝Node.js
有兩種安裝方式:
Windows 安裝包(.msi)
一直點(diǎn)下一步就好了圆兵,將node加入環(huán)境變量,安裝的時(shí)候它好像是默認(rèn)不添加的枢贿,如果不想自己手動(dòng)添加的話殉农,建議勾選一下Add to PATH。
安裝后檢測(cè)PATH 環(huán)境變量是否配置了Node.js萨咕,點(diǎn)擊開始=》運(yùn)行=》輸入cmd =》輸入path
就會(huì)輸出所有已配置的path
如果node已添加到環(huán)境變量中使用node --version
可以檢查Node.js版本统抬。Windows二進(jìn)制文件(.exe)安裝
依然是一連串的下一步。
Ubuntu 上安裝Node.js
源碼安裝
以下將介紹在Ubuntu Linux 下安裝Node.js危队。其他的Linux系統(tǒng)聪建,如Centos 等類似如下安裝步驟:
在GitHub上獲取Node.js 源碼:
$ sudo git clone https://github.com/nodejs/node.git
Cloning into 'node' ...
修改目錄權(quán)限:
$ sudo chmod -R 755 node
使用./configure 創(chuàng)建編譯文件,并按照:
$ cd node
$ sudo ./configure
$ sudo make
$ sudo make install
Ubunto apt-get命令安裝
命令格式如下:
sudo apt-get install nodejs
sudo apt-get install npm
CentOS 下安裝NOde.js
- 下載源碼
cd /usr/local/src/
wget 源碼URL
- 解壓源碼
tar zxvf 安裝包名
- 編譯安裝
cd node-v0.10.24
./configure --prefix=/usr/local/node/0.10.24
make make install
- 配置NODE_HOME 茫陆,進(jìn)入profile 編輯環(huán)境變量
vim /etc/profile
設(shè)置nodejs環(huán)境變量金麸,在 export PATH USER LOGNAME MAIL HOSTNAME HISTSIZE HISTCONTROL
一行的上面添加如下內(nèi)容:
#set for nodejs
export NODE_HOME=/usr/local/node/0.10.24
export PATH=$NODE_HOME/bin:$PATH
:wq
保存并退出,編譯/ect/profile 使配置生效簿盅。
source /ect/profile
驗(yàn)證是否安裝配置成功
node -v
注:Nodejs 官網(wǎng)提供了編譯好的Linux 二進(jìn)制包挥下,你也可以下載下來直接應(yīng)用。
創(chuàng)建第一個(gè)應(yīng)用
如果我們使用PHP來編寫后端的代碼時(shí)桨醋,需要Apache 或者Nginx 的HTTP 服務(wù)器棚瘟,并配上 mod_php5 模塊和 php_cgi。
從這個(gè)角度看喜最,整個(gè)“接收HTTP請(qǐng)求并提供Web頁面”的需求根本不需要PHP來處理偎蘸。
不過,對(duì)Node.js來說,概念完全不一樣了迷雪。使用Node.js時(shí)限书,我們不僅僅在實(shí)現(xiàn)一個(gè)應(yīng)用,同時(shí)還實(shí)現(xiàn)了整個(gè)HTTP服務(wù)器章咧。
事實(shí)上倦西,我們的web應(yīng)用及對(duì)應(yīng)的web服務(wù)器基本上是一樣的。
在我們創(chuàng)建Node.js 第一個(gè)“hello赁严,world扰柠!”應(yīng)用之前,讓我們先了解一下Node.js 應(yīng)用是由哪幾部分組成的:
- 引入 http 模塊:我們可以使用require 指令來載入Node.js 模塊
- 創(chuàng)建服務(wù)器:服務(wù)器可以監(jiān)聽客戶端的請(qǐng)求误澳,類似于Apache耻矮、Nginx等http服務(wù)器。
- 接收請(qǐng)求與響應(yīng)請(qǐng)求忆谓。服務(wù)器很容易創(chuàng)建裆装,客戶端可以使用瀏覽器或終端發(fā)送http請(qǐng)求,服務(wù)器接收請(qǐng)求后返回響應(yīng)數(shù)據(jù)倡缠。
創(chuàng)建Node.js 應(yīng)用
步驟一 引入http 模塊
我們使用 require 指令來載入http 模塊哨免,并將實(shí)例化的http賦值給變量http,實(shí)例如下:
var http = require("http");
步驟二 創(chuàng)建服務(wù)器
接下來我們使用 http.createServer() 方法創(chuàng)建服務(wù)器昙沦,并使用listen 方法綁定 8888 端口琢唾。函數(shù)通過request,response 參數(shù)來接收和響應(yīng)數(shù)據(jù)盾饮。
實(shí)例如下采桃,在項(xiàng)目根目錄下創(chuàng)建 server.js 文件,并寫入一下代碼:
var http = require('http');
http.createSerer(function(request,response){
//發(fā)送HTTP頭部
// HTTP 狀態(tài)值 : 200 OK
//內(nèi)容類型:text/plain
response.writeHead(200,{"Content-Type":"text/plain"});
// 發(fā)送響應(yīng)數(shù)據(jù) “hello丘损,world普办!”
response.end("Hello World\n");
}).listen(8888);
// 終端打印如下信息
console.log("Server running at http://127.0.0.1:8888/");
以上代碼我們完成了一個(gè)可以工作的http服務(wù)器。
使用node 命令執(zhí)行以上的代碼:
node server.js
Server running at http://127.0.0.1:8888/
接下來徘钥,打開瀏覽器訪問http://127.0.0.1:8888/ 衔蹲,你會(huì)看到一個(gè)寫著“hello world”的網(wǎng)頁。
分析Node.js 的HTTP服務(wù)器:
- 第一行請(qǐng)求(require)Node.js 自帶的http 模塊呈础,并且把他賦值給http 變量舆驶。
- 接下來我們調(diào)用http 模塊提供的函數(shù):createServer 。這個(gè)函數(shù)會(huì)返回一個(gè)對(duì)象而钞,這個(gè)對(duì)象有一個(gè)叫做listen 的方法沙廉,這個(gè)方法有一個(gè)數(shù)值參數(shù),指定這個(gè)HTTP服務(wù)器監(jiān)聽的端口號(hào)臼节。
實(shí)例演示
image.png
npm使用介紹
這里只簡(jiǎn)單介紹npm的使用撬陵,詳細(xì)的內(nèi)容可以訪問npm中文網(wǎng)的文檔俱病,寫的也挺詳細(xì)的https://www.npmjs.com.cn/ 。
NPM 是隨同NodeJS一起安裝的包管理工具袱结,能解決NodeJS代碼部署上的很多問題,常見的使用場(chǎng)景有如下幾種:
- 允許用戶從NPM服務(wù)器下載別人編寫的第三方包到本地使用途凫。
- 允許用戶從NPM服務(wù)器下載并安裝別人編寫的命令行程序到本地使用垢夹。
- 允許用戶將自己編寫的包或命令程序上傳到NPM服務(wù)器供別人使用。
新版的nodejs 已經(jīng)集成了npm维费,我們可以通過輸入"npm -v"來測(cè)試是否成功安裝果元。出現(xiàn)版本提示表示安裝成功。
如果你安裝的是舊版本的npm 犀盟, 可以很容易地通過 npm 命令來升級(jí)而晒,命令如下:
$ sudo npm install npm -g
/usr/local/bin/npm -> /usr/local/lib/node_modules/npm/bin/npm-cli.js
npm@2.14.2 /usr/local/lib/node_modules/npm
如果是Windows 系統(tǒng)使用以下命令即可:
npm install npm -g
使用npm 命令安裝模塊
npm 安裝 Node.js 模塊語法格式如下:
$ npm install <Module Name>
以下實(shí)例,我們使用 npm 命令安裝常用的Node.js web框架模塊 express :
$ npm install express
安裝好之后阅畴,express就放在了工程目錄下的node_modules 目錄中倡怎,因此在代碼中只需要通過require('express') 的方式就好,無需指定第三方包路徑贱枣。
var express = require("express");
全局安裝與本地安裝
npm 的包安裝分為本地安裝(local)监署、全局安裝(global)兩種,從敲的命令來看纽哥,差別只是有沒有-g而已钠乏,比如:
npm install express #本地安裝
npm install express -g #全局安裝
如果出現(xiàn)以下錯(cuò)誤:
npm err! Error: connect ECONNREFUSED 127.0.0.1:8087
解決方法為:
$ npm config set proxy null
本地安裝
- 將安裝包放在 ./node_modules下(運(yùn)行npm命令時(shí)所在的目錄),如果沒有node_modules 目錄春塌,會(huì)在當(dāng)前執(zhí)行npm 命令的目錄下生成node_modules 目錄晓避。
- 可以通過require() 來引入本地安裝包。
全局安裝
- 將安裝包放在 /usr/local 下或者你 node 的安裝目錄
- 可以直接在命令行里使用
如果你希望具備兩者功能只壳,則需要在兩個(gè)地方安裝它或者使用 npm link
接下來我們使用全局安裝express
$ npm install express -g
安裝過程輸出內(nèi)容俏拱,第一行輸出了模塊的版本號(hào)及安裝位置。
查看安裝信息
你可以使用以下命令來查看所有全局安裝的模塊:
$ npm list -g
如果要查看某個(gè)模塊的版本號(hào)吕世,可以使用命令如下:
$ npm list <Module name>
使用 package.json
package.json 位于模塊的目錄下彰触,用于定義包的屬性。接下來看下 express 包的 package.json 文件命辖,位于 node_modules/express/package.json 內(nèi)容:
略
Package.json 屬性說明
- name 包名
- version 包的版本號(hào)
- description 包的描述
- homepage 包的官網(wǎng)URL
- author 包的作者姓名
- contributors 包的其他貢獻(xiàn)者姓名
- dependencies 依賴包列表况毅。如果依賴包沒有安裝,npm會(huì)自動(dòng)將依賴包安裝在 node_modules目錄下尔艇。
- repository 包代碼存放放的地方的類型尔许,可以是git 或svn,git可在GitHub上终娃。
- main 指定了程序的主入口文件味廊,require(‘moduleName’)就會(huì)加載這個(gè)文件。這個(gè)字段默認(rèn)值是模塊跟目錄下面的 index.js
- keywords 關(guān)鍵字
卸載模塊
$ npm uninstall express
更新模塊
$ npm update express
創(chuàng)建模塊
創(chuàng)建模塊,package.json 文件是必不可少的余佛。我們可以使用npm 生成package.json文件柠新,生成的文件包含了基本的結(jié)果。
$ npm init
接下來我們可以使用以下命令在npm資源庫中注冊(cè)用戶(使用郵箱注冊(cè)):
$ npm add user
Username : mcmohd
Password:
Email : (this IS public) mcmohd@mail.com
接下來我們就用以下命令來發(fā)布模塊:
$ npm publish
如果你以上步驟都操作正確辉巡,你就可以跟其他模塊一樣使用npm來安裝恨憎。
版本號(hào)
使用NPM下載和發(fā)布代碼時(shí)都會(huì)接觸到版本號(hào)。NPM 使用語義版本號(hào)來管理代碼郊楣,這里簡(jiǎn)單介紹以下憔恳。
語義版本號(hào)分為X.Y.Z三位,分別代表主版本號(hào)净蚤、次版本號(hào)和補(bǔ)丁版本號(hào)钥组。當(dāng)代碼變更時(shí),版本號(hào)按以下原則更新今瀑。
- 如果只是修復(fù)bug程梦,需要更新Z位
- 如果是新增了功能,但是向下兼容放椰,需要更新Y位作烟。
- 如果有大變動(dòng),向下不兼容砾医,需要更新X位拿撩。
版本號(hào)有了保證后,在申明第三方包依賴時(shí)如蚜,除了可依賴于一個(gè)固定版本號(hào)外压恒,還可依賴于某個(gè)范圍的版本號(hào)。
例如"argv":"0.0.x"
表示依賴于0.0.x系列的最新版argv错邦。
npm支持的所有版本號(hào)范圍指定方式可以查看官方文檔探赫。
NPM常用命令
除了本章介紹的部分外,NPM還提供了很多功能撬呢,package.json里也有很多其他有用的字段伦吠。
在npmjs可查看官方文檔,這里再介紹一些NPM常用命令:
- 使用
npm help
可查看所有命令魂拦。 - 使用
npm help <command>
可查看某條命令的詳情幫助毛仪,例如npm help install
- 在package.json 所在目錄下使用
npm install . -g
可在本地安裝當(dāng)前命令行程序,可用于發(fā)布前的本地測(cè)試芯勘。 - 使用
npm update <package>
可以把當(dāng)前目錄下node_modules子目錄里的對(duì)應(yīng)模塊更新至最新版箱靴。 - 使用
npm update <package> -g
可以把全局安裝的對(duì)應(yīng)命令行程序更新至最新版 - 使用
npm cache clear
可以清空NPM本地緩存,用于對(duì)付使用相同版本號(hào)發(fā)布新版本代碼的人 - 使用
npm unpublish <package>@<version>
可以撤銷發(fā)布自己發(fā)布過的某個(gè)版本代碼
使用淘寶鏡像
大家都知道國(guó)內(nèi)鏡像使用npm 的官方鏡像是非常慢的荷愕,這里推薦使用淘寶NPM鏡像衡怀。
淘寶NPM鏡像是一個(gè)完整npmjs.org鏡像棍矛,你可以用此代替官方版本(只讀),同步頻率目前為10分鐘一次以保證盡量與官方同步抛杨。
你可以使用淘寶定制的cnpm(gzip壓縮支持)命令行工具代替默認(rèn)的npm :
$ npm install -g cnpm --registry=https://registry.npm.taobao.org
這樣就可以使用cnpm 命令來安裝模塊了:
$ cnpm install [name]
更多信息可以查閱:http://npm.taobao.org
本章總結(jié):
- npm 的常用使用場(chǎng)景
- npm 的升級(jí)
- 使用 npm 命令安裝模塊
- 全局安裝與本地安裝
- 查看安裝信息
- 使用package.json及package.json 屬性說明
- 卸載模塊
- 更新模塊
- 搜索模塊
- 創(chuàng)建模塊
- 注冊(cè)npm庫用戶
- 發(fā)布模塊
- 版本號(hào)介紹
- NPM常用命令
- 使用淘寶鏡像
REPL
什么是REPL
REPL : Read Eval Print Loop : 交互式解釋器够委。表示電腦的一個(gè)環(huán)境,類似Windows 系統(tǒng)的終端或Unix/Linux shell怖现,我們可以在終端中輸入命令慨绳,并接收系統(tǒng)的響應(yīng)。
Node 自帶了交互式解釋器真竖,可以執(zhí)行以下任務(wù):
- 讀取 - 讀取用戶輸入,解析輸入的JavaScript 數(shù)據(jù)結(jié)構(gòu)并存儲(chǔ)在內(nèi)存中
- 執(zhí)行 - 執(zhí)行輸入的數(shù)據(jù)結(jié)構(gòu)
- 打印 - 輸出結(jié)果
- 循環(huán) - 循環(huán)操作以上步驟直到用戶兩次按下 Ctrl - c 按鈕退出
Node 的交互解釋器可以很好的調(diào)試JavaScript代碼厌小。
開始學(xué)習(xí) REPL
我們可以輸入以下命令來啟動(dòng)Node 的終端;
$ node
>
這時(shí)我們就可以在> 后輸入簡(jiǎn)單的表達(dá)式恢共,并按下回車鍵來運(yùn)算結(jié)果。
簡(jiǎn)單的表達(dá)式運(yùn)算
接下來我們?cè)贜ode.js REPL 的命令窗口中執(zhí)行簡(jiǎn)單的數(shù)學(xué)運(yùn)算:
$ node
> 1 +4
5
> 5 / 2
2.5
> 3 * 6
18
> 4 - 1
3
> 1 + ( 2 * 3 ) - 4
3
>
使用變量
你可以將數(shù)據(jù)存儲(chǔ)在變量中璧亚,并在你需要的時(shí)候使用它讨韭。
變量聲明需要使用var 關(guān)鍵字,如果沒有使用var 關(guān)鍵字癣蟋,變量會(huì)直接打印出來透硝。
使用var 關(guān)鍵字的變量可以使用 console.log() 來輸出變量。
$ node
> x = 10
10
> var y = 10
undefined
> x + y
20
> console.log("Hello World")
Hello World
undefined
> console.log("www.runoob.com")
www.runoob.com
undefined
多行表達(dá)式
Node REPL 支持輸入多行表達(dá)式疯搅,這就有點(diǎn)類似JavaScript濒生。接下來我們執(zhí)行一個(gè)do-while 循環(huán):
$ node
> var x = 0
undefined
> do {
... x++;
... console.log("x: " + x);
... } while ( x < 5 );
x: 1
x: 2
x: 3
x: 4
x: 5
undefined
>
...三個(gè)點(diǎn)的符號(hào)是系統(tǒng)自動(dòng)生成的,你回車換行后即可幔欧。Node 會(huì)自動(dòng)檢測(cè)是否為連續(xù)的表達(dá)式罪治。
下劃線(_)變量
你可以使用下劃線(_)獲取上一個(gè)表達(dá)式的運(yùn)算結(jié)果:
> var x=10
undefined
> var y=10
undefined
> x+y
20
> var sum=_
undefined
> sum
20
>
REPL 命令
- Ctrl + c : 退出當(dāng)前終端
- Ctrl + c 兩次 : 退出Node REPL
- Ctrl + d : 退出Node REPL
- 向上、向下鍵 : 查看輸入的歷史命令
- tab鍵 : 列出當(dāng)前命令
- .help : 列出使用命令
- .break : 退出多行表達(dá)式
- .clear : 退出多行表達(dá)式
- .save filename : 保存當(dāng)前的REPL 會(huì)話到指定文件
- .load filename : 載入當(dāng)前Node REPL 會(huì)話的文件內(nèi)容
停止REPL
前面我們已經(jīng)提到按兩下 Ctrl+c 鍵就能退出REPL礁蔗。
回調(diào)函數(shù)
Node.js 異步編程的直接體現(xiàn)就是回調(diào)觉义。
異步編程依托于回調(diào)來實(shí)現(xiàn),但不能說使用了回調(diào)后程序就異步化了浴井。
回調(diào)函數(shù)在完成任務(wù)后就會(huì)被調(diào)用晒骇,Node 使用了大量的回調(diào)函數(shù),Node 所有API 都支持回調(diào)函數(shù)磺浙。
例如洪囤,我們可以一邊讀取文件,一邊執(zhí)行其他命令屠缭,在文件讀取完成后箍鼓,我們將文件內(nèi)容作為回調(diào)函數(shù)的參數(shù)返回。這樣在執(zhí)行代碼時(shí)就沒有阻塞或等待文件I/O 操作呵曹。這就大大提高了 Node.js 的性能款咖,可以處理大量的并發(fā)請(qǐng)求何暮。
回調(diào)函數(shù)一般作為最后一個(gè)參數(shù)出現(xiàn):
function foo1(name, age, callback) { }
function foo2(value, callback1, callback2) { }
阻塞代碼示例
創(chuàng)建一個(gè)文件 input.txt ,內(nèi)容如下:
我多想成為一顆星
另一個(gè)我與我平行
每一次夢(mèng)中的愿景
在一顆星上實(shí)現(xiàn)
仰望星空铐殃,偌大的時(shí)空
暢想著多重可能
淚水蒸發(fā)在悲傷
歡愉流淌于溪水
彼此交融在思想
交換了場(chǎng)景海洼,在不同的星上
我坐落在一顆星上
在色彩斑斕的世界里遙望
當(dāng)光明沉睡
寄送來的一顆星
是屬于我的平行
作者:不俗小七
鏈接:http://www.reibang.com/p/5bea3b0cb154
來源:簡(jiǎn)書
著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán)富腊,非商業(yè)轉(zhuǎn)載請(qǐng)注明出處坏逢。
創(chuàng)建 main.js 文件,代碼如下:
var fs = require("fs")
var data = fs.readFileSync("input.txt");
console.log(data.toString());
console.log("程序執(zhí)行結(jié)束赘被!")
以上代碼執(zhí)行結(jié)果如下:
D:\WorkStudy\StudySpace\Nodejs\runoob>node main.js
我多想成為一顆星
另一個(gè)我與我平行
每一次夢(mèng)中的愿景
在一顆星上實(shí)現(xiàn)
仰望星空是整,偌大的時(shí)空
暢想著多重可能
淚水蒸發(fā)在悲傷
歡愉流淌于溪水
彼此交融在思想
交換了場(chǎng)景,在不同的星上
我坐落在一顆星上
在色彩斑斕的世界里遙望
當(dāng)光明沉睡
寄送來的一顆星
是屬于我的平行
作者:不俗小七
鏈接:http://www.reibang.com/p/5bea3b0cb154
來源:簡(jiǎn)書
著作權(quán)歸作者所有民假。商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán)浮入,非商業(yè)轉(zhuǎn)載請(qǐng)注明出處。
程序執(zhí)行結(jié)束羊异!
D:\WorkStudy\StudySpace\Nodejs\runoob>
非阻塞代碼實(shí)例
依然使用上面創(chuàng)建的input.txt 文件事秀。
創(chuàng)建 main2.js 文件,代碼如下:
var fs = require("fs");
fs.readFile('input.txt', function (err, data) {
if (err) return console.error(err);
console.log(data.toString());
});
console.log("程序執(zhí)行結(jié)束!");
以上代碼執(zhí)行結(jié)果如下:
D:\WorkStudy\StudySpace\Nodejs\runoob>node main.js
我多想成為一顆星
另一個(gè)我與我平行
每一次夢(mèng)中的愿景
在一顆星上實(shí)現(xiàn)
仰望星空野舶,偌大的時(shí)空
暢想著多重可能
淚水蒸發(fā)在悲傷
歡愉流淌于溪水
彼此交融在思想
交換了場(chǎng)景易迹,在不同的星上
我坐落在一顆星上
在色彩斑斕的世界里遙望
當(dāng)光明沉睡
寄送來的一顆星
是屬于我的平行
作者:不俗小七
鏈接:http://www.reibang.com/p/5bea3b0cb154
來源:簡(jiǎn)書
著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán)平道,非商業(yè)轉(zhuǎn)載請(qǐng)注明出處睹欲。
程序執(zhí)行結(jié)束!
D:\WorkStudy\StudySpace\Nodejs\runoob>
以上兩個(gè)實(shí)例我們了解了阻塞與非阻塞調(diào)用的不同一屋。第一個(gè)實(shí)例在文件讀取完后才執(zhí)行完程序句伶。第二個(gè)實(shí)例我們不需要等待文件讀取完,這樣就可以在讀取文件時(shí)同時(shí)執(zhí)行接下來的代碼陆淀,大大提高了程序的性能考余。
因此,阻塞時(shí)按順序執(zhí)行的轧苫,而非阻塞時(shí)不需要按順序的楚堤,所以如果需要處理回調(diào)函數(shù)的參數(shù),我們就要寫在回調(diào)函數(shù)內(nèi)含懊。
回調(diào)疑惑
不過我這里有個(gè)問題:用非阻塞方式時(shí)身冬,當(dāng)我在讀文件的時(shí)候同時(shí)在執(zhí)行其他的代碼,但是這段代碼執(zhí)行到一個(gè)地方需要用到讀取文件后的結(jié)果岔乔,這時(shí)酥筝,我該怎么辦了呢?把外面這段代碼寫到回調(diào)函數(shù)里面去嗎雏门?這樣的話嘿歌,我外面的代碼就相當(dāng)于在回調(diào)中阻塞了掸掏。有什么解決方案嗎?
事件循環(huán)
Node.js 事件循環(huán)
Node.js 是單進(jìn)程單線程應(yīng)用程序宙帝,但是因?yàn)閂8 引擎提供的異步執(zhí)行回調(diào)接口丧凤,通過這些接口可以處理大量的并發(fā)溺欧,所以性能非常高朗涩。
Node.js 幾乎每一個(gè)API 都是支持回調(diào)函數(shù)的。
Node.js 基本上所有的事件機(jī)制都是用設(shè)計(jì)模式中觀察者模式實(shí)現(xiàn)拉盾。
Node.js 單線程類似進(jìn)入一個(gè)while(true)的事件循環(huán)靴患,直到?jīng)]有事件觀察者退出仍侥,每個(gè)異步事件都生成一個(gè)事件觀察者,如果有事件發(fā)生就調(diào)用該回調(diào)函數(shù)鸳君。
事件驅(qū)動(dòng)程序
Node.js 使用事件驅(qū)動(dòng)模型访圃,當(dāng)web server接收到請(qǐng)求,就把它關(guān)閉然后進(jìn)行處理相嵌,然后去服務(wù)下一個(gè)web請(qǐng)求。
當(dāng)這個(gè)請(qǐng)求完成况脆,它被放回處理隊(duì)列饭宾,當(dāng)?shù)竭_(dá)隊(duì)列開頭,這個(gè)結(jié)果被返回給用戶格了。
這個(gè)模型非常高效可擴(kuò)展性非常強(qiáng)看铆,因?yàn)閣ebserver 一直接受請(qǐng)求而不等待任何讀寫操作。(這也被稱之為非阻塞式IO或者時(shí)間驅(qū)動(dòng)IO)
在事件驅(qū)動(dòng)模型中盛末,會(huì)生成一個(gè)主循環(huán)來監(jiān)聽事件弹惦,當(dāng)檢測(cè)到事件時(shí)觸發(fā)回調(diào)函數(shù)。
整個(gè)事件驅(qū)動(dòng)的流程就是這么實(shí)現(xiàn)的悄但,非常簡(jiǎn)潔棠隐。有點(diǎn)類似于觀察者模式,事件相當(dāng)于一個(gè)主題(Subject)檐嚣,而所有注冊(cè)到這個(gè)事件上的處理函數(shù)相當(dāng)于觀察者(Observer)助泽。
Node.js 有多個(gè)內(nèi)置的事件,我們可以通過引入events 模塊嚎京,并通過實(shí)例化 EventEmitter 類來綁定和監(jiān)聽事件嗡贺,如下實(shí)例:
// 引入 events 模塊
var events = require("events");
// 創(chuàng)建eventEmitter 對(duì)象
var eventEmitter = new events.EventEmitter();
綁定事件處理程序:
eventEmitter.on("eventName",eventHandler);
觸發(fā)事件:
eventEmitter.emit("eventName");