前言
1萧豆、nodej是什么奸披?what
2、為什么用涮雷? why
3阵面、怎么用?how
一洪鸭、Nodejs介紹和特色
1样刷、nodejs是什么?
Node.js 不是一門(mén)語(yǔ)言览爵,而是一個(gè)開(kāi)發(fā)平臺(tái)(有對(duì)應(yīng)的語(yǔ)言和實(shí)現(xiàn)特定功能的api)置鼻,是一個(gè)用C++
開(kāi)發(fā)的 ,事件驅(qū)動(dòng) I/O 服務(wù)端 JavaScript 環(huán)境蜓竹,是一個(gè)基于 Chrome V8 引擎的 JavaScript 運(yùn)行環(huán)境箕母,V8 引擎執(zhí)行 Javascript 的速度非炒⒚辏快,性能非常好嘶是,
用于方便地搭建響應(yīng)速度快邑茄、易于擴(kuò)展的網(wǎng)絡(luò)應(yīng)用,它有非阻塞俊啼、事件驅(qū)動(dòng)模型的特性肺缕,有輕量高效的特點(diǎn),適用于分布式設(shè)備上運(yùn)行數(shù)據(jù)密集型的實(shí)時(shí)應(yīng)用
Node.js是一個(gè)用C++
開(kāi)發(fā)的 授帕、服務(wù)器端同木、單阻塞式I/O、事件驅(qū)動(dòng)模型跛十、基于 Chrome V8 引擎的 JaveScript運(yùn)行環(huán)境( 即Javascript 語(yǔ)言解釋器)
2彤路、安裝配置
2.1、node下載地址
https://nodejs.org/en/download/
LTS版本:長(zhǎng)期支持版芥映,即穩(wěn)定版(建議) Current版本:最新版 安裝node后在cmd下運(yùn)行node -v即可查看安裝的node.js版本如果安裝成功卻提示node不是內(nèi)部或者外部的命令洲尊。則需要手動(dòng)配置環(huán)境變量
2.2、配置環(huán)境變量
為什么要配置環(huán)境變量:一般情況下奈偏,cmd環(huán)境想要運(yùn)行一個(gè)文件坞嘀,例如node.exe,那么對(duì)應(yīng)的路徑下必須有node.exe這個(gè)文件才能啟動(dòng)惊来,否則就會(huì)提示命令不存在丽涩。 配置環(huán)境變量就是告訴電腦,如果我們輸入的命令在當(dāng)前路徑下沒(méi)有對(duì)應(yīng)的執(zhí)行文件裁蚁,那么就去其他路徑下查看矢渊,配置環(huán)境變量也就是添加一個(gè)可供查找的絕對(duì)路徑 如何配置環(huán)境變量: 右鍵計(jì)算機(jī)>屬性>系統(tǒng)高級(jí)設(shè)置>高級(jí)>環(huán)境變量
選擇Path這個(gè)變量名,對(duì)應(yīng)的變量值是有若干的路徑組成的每個(gè)路徑用";"隔開(kāi)枉证,添加時(shí)也記得加 分號(hào) 矮男,這里node.js安裝是已經(jīng)自動(dòng)添加了環(huán)境變量,所以里面已經(jīng)有node.js的路徑了室谚,如果沒(méi)有毡鉴,就要手動(dòng)添加
2.3、node的版本管理工具(nvm)
1.安裝nvm(Node Version Manager )2.常用命令:cmd窗口輸入命令
- nvm v:顯示nvm版本,如果有則表示安裝成功舞萄。
- nvm list: 列出已經(jīng)安裝的node.js版本
- nvm uninstall 版本號(hào):卸載指定版本的nodejs眨补。
- nvm install latest:安裝最新版node.js
- nvm install 版本號(hào):安裝指定的node.js版本
- nvm ues 版本號(hào):使用指定的node.js版本
2.4、自動(dòng)重啟服務(wù)器(node-dev/nodemon/supervisor)
2.4.1倒脓、node-dev
1、node-dev是一個(gè)node.js開(kāi)發(fā)工具含思,當(dāng)文件被修改時(shí)崎弃,它會(huì)自動(dòng)重新啟動(dòng)node進(jìn)程
// 全局安裝
npm install -g node-dev
// 運(yùn)行服務(wù)
node-dev index.js
2甘晤、Node-dev 可以當(dāng)有js文件修改后自動(dòng)去重啟nodejs進(jìn)程, 這樣就不用每次ctrl+c 終止在重啟了,而且不僅支持js文件, .json .node .coffee 文件格式都支持
2.4.2饲做、nodemon
1线婚、 Nodemon是一個(gè)使用工具逸邦,它將會(huì)見(jiàn)監(jiān)視源文件中任何的更改并自動(dòng)重啟服務(wù)器
// 全局安裝
npm install -g nodemon
// 運(yùn)行服務(wù)
nodemon index.js
2菇用、實(shí)際項(xiàng)目中可在package.json中配置
{
"name": "nodejs",
"version": "1.0.0",
"description": "nodejs測(cè)試",
"main": "index.js",
"dependencies": {},
"devDependencies": {},
"scripts": {
"start": "nodemon index.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC"
}
2.4.3、npm
1强窖、npm是Node Package Manage的縮寫(xiě)泪姨,意思是node的包管理系統(tǒng)
- NPM提供了很多命令游沿,例如
install
和publish
,使用npm help
可查看所有命令肮砾。 - 使用
npm help <command>
可查看某條命令的詳細(xì)幫助诀黍,例如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>
可以撤銷(xiāo)發(fā)布自己發(fā)布過(guò)的某個(gè)版本代碼洋幻。
2模叙、使用淘寶鏡像
// 使用淘寶鏡像
npm install -g cnpm --registry=https://registry.npmmirror.com
// 使用cnpm 命令來(lái)安裝模塊
cnpm install [name]
3、yarn
3鞋屈、Nodejs三大特色
故事背景:
高級(jí)餐廳(傳統(tǒng)服務(wù)器語(yǔ)言):(給每一個(gè)用戶分配一個(gè)服務(wù)員(多個(gè)服務(wù)員范咨,多線程)—>用戶看菜單->等待I/O操作->要點(diǎn)的菜告訴服務(wù)員-> I/O 操作結(jié)束后線程繼續(xù)執(zhí)行->看菜單,服務(wù)員閑置到你點(diǎn)完( I/O 操作結(jié)束) -->阻塞式 I/O
小餐館(nodejs):所有用戶共享一個(gè)服務(wù)員(一個(gè)服務(wù)員厂庇,單線程)-->用戶看菜單(等待I/O操作)-->您先看著菜單渠啊,點(diǎn)好了叫我(回調(diào)函數(shù))-->顧客點(diǎn)完后會(huì)主動(dòng)叫服務(wù)員(執(zhí)行回調(diào)函數(shù))
3.1. 單線程
3.1.1、和其他后臺(tái)語(yǔ)言不一樣权旷,Node.js 不會(huì)為每一個(gè)客戶建立一個(gè)新的線程替蛉。而僅僅使用一個(gè)線程。當(dāng)有用戶鏈接了拄氯,就會(huì)出發(fā)一個(gè)內(nèi)部事件躲查,經(jīng)過(guò)非阻塞I/O、事件驅(qū)動(dòng)機(jī)制译柏,讓Node.js程序在宏觀上也是并行的镣煮。
服務(wù)器單線程帶來(lái)的好處,操作系統(tǒng)徹底再也不用有線程建立鄙麦、銷(xiāo)毀的時(shí)間開(kāi)銷(xiāo)典唇。
3.1.2镊折、相對(duì)于php、java后端語(yǔ)言的多線程介衔,nodej采用異步單線程優(yōu)勢(shì)
節(jié)約服務(wù)器內(nèi)存(線程越多占用的內(nèi)存越多) 節(jié)約上下文切換的時(shí)間(由于多線程實(shí)現(xiàn)原理是通過(guò)切換時(shí)間片來(lái)實(shí)現(xiàn)的 所以線程越多 需要切換的次數(shù)就越多 耗費(fèi)的時(shí)間越長(zhǎng)) 不存在鎖的問(wèn)題 (java通常會(huì)通過(guò)給進(jìn)程加鎖來(lái)解決多個(gè)線程訪問(wèn)同一資源的問(wèn)題 而單線程就不存在這個(gè)問(wèn)題)
固然它的優(yōu)點(diǎn)也是它的劣勢(shì)恨胚,一個(gè)用戶形成了線程的崩潰,整個(gè)服務(wù)也會(huì)崩潰炎咖。
3.1.3赃泡、瀏覽器線程(了解)
JS引擎線程 .GUI渲染線程(和JS引擎線程互斥 兩者只有一者正在執(zhí)行 不會(huì)同時(shí)進(jìn)行) 事件觸發(fā)線程 定時(shí)器觸發(fā)線程 異步http請(qǐng)求線程
3.2. 非阻塞 I/O(no-blocking I/O)
3.2.1、正常來(lái)講乘盼,I/O 阻塞了代碼的執(zhí)行升熊,極大地下降了程序的執(zhí)行效率。因?yàn)?Node.js 采用了非阻塞 I/O 機(jī)制蹦肴,在執(zhí)行了訪問(wèn)數(shù)據(jù)庫(kù)的代碼以后僚碎,將當(dāng)即轉(zhuǎn)而執(zhí)行其后面的代碼,把數(shù)據(jù)庫(kù)返回的處理代碼放到回調(diào)函數(shù)中阴幌,從而提升了程序的執(zhí)行效率
3.2.2 理解非阻塞和同步異步
同步和異步起決于被調(diào)用者 阻塞和非阻塞起決于調(diào)用者
阻塞是按順序執(zhí)行的勺阐,而非阻塞是不需要按順序的
3.3. 事件驅(qū)動(dòng)(event-driven)
在 Node 中,客戶端請(qǐng)求創(chuàng)建鏈接矛双,提交數(shù)據(jù)等行為渊抽,會(huì)觸發(fā)相應(yīng)的事件,在一個(gè)時(shí)刻议忽,只能執(zhí)行一個(gè)事件回調(diào)函數(shù)懒闷,可是在執(zhí)行一個(gè)事件回調(diào)的中途,能夠轉(zhuǎn)而處理其余事件栈幸,而后繼續(xù)執(zhí)行原事件的回調(diào)函數(shù)愤估,這種處理機(jī)制,稱為“事件環(huán)”機(jī)制速址。
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ì)列開(kāi)頭默刚,這個(gè)結(jié)果被返回給用戶。這個(gè)模型非常高效可擴(kuò)展性非常強(qiáng)逃魄,因?yàn)?webserver 一直接受請(qǐng)求而不等待任何讀寫(xiě)操作荤西。(這也稱之為非阻塞式IO或者事件驅(qū)動(dòng)IO)在事件驅(qū)動(dòng)模型中,會(huì)生成一個(gè)主循環(huán)來(lái)監(jiān)聽(tīng)事件,當(dāng)檢測(cè)到事件時(shí)觸發(fā)回調(diào)函數(shù)皂冰。
[圖片上傳失敗...(image-64461e-1678162204288)]
整個(gè)事件驅(qū)動(dòng)的流程就是這么實(shí)現(xiàn)的店展,非常簡(jiǎn)潔养篓。有點(diǎn)類(lèi)似于觀察者模式秃流,事件相當(dāng)于一個(gè)主題(Subject),而所有注冊(cè)到這個(gè)事件上的處理函數(shù)相當(dāng)于觀察者
Node.js 有多個(gè)內(nèi)置的事件柳弄,我們可以通過(guò)引入 events 模塊舶胀,并通過(guò)實(shí)例化 EventEmitter 類(lèi)來(lái)綁定和監(jiān)聽(tīng)事件,如下實(shí)例:
[圖片上傳失敗...(image-effb9d-1678159779170)]
Node.js中所有的I/O都是異步的碧注,回調(diào)函數(shù)嚣伐,套回調(diào)函數(shù)
4、為什么要用Nodejs萍丐,優(yōu)勢(shì)
它是一個(gè)Javascript運(yùn)行環(huán)境(簡(jiǎn)單容易上手)
依賴于Chrome V8引擎進(jìn)行代碼解釋(號(hào)稱世界上最快的解釋器)
事件驅(qū)動(dòng)(高并發(fā)處理速度優(yōu)勢(shì))
非阻塞I/O(創(chuàng)建新的線程去執(zhí)行轩端,不會(huì)阻塞主線程。動(dòng)作并行執(zhí)行逝变,速度更快)--->適合I/O密集型應(yīng)用
輕量基茵、可伸縮,適于實(shí)時(shí)數(shù)據(jù)交互應(yīng)用(由高并發(fā)特性決定)
單進(jìn)程壳影,單線程(不會(huì)占用大量的內(nèi)存)
處理高并發(fā)場(chǎng)景性能更佳
node 最大的優(yōu)勢(shì)就是性能強(qiáng)拱层,同樣的服務(wù)器性能使用 node 可以比傳統(tǒng)的服務(wù)器語(yǔ)言多容納一百倍的用戶(對(duì)于不同的任務(wù)有不同的差別, I/O 操作越多宴咧,node優(yōu)勢(shì)越明顯)(每個(gè)線程2M根灯,理論8g內(nèi)存,就是4000用戶掺栅,nodejs就是4萬(wàn))
5烙肺、Nodejs劣勢(shì)
1、不適合CPU密集型應(yīng)用氧卧;CPU密集型應(yīng)用給Node帶來(lái)的挑戰(zhàn)主要是:由于JavaScript單線程的原因桃笙,如果有長(zhǎng)時(shí)間運(yùn)行的計(jì)算(比如大循環(huán)),將會(huì)導(dǎo)致CPU時(shí)間片不能釋放假抄,使得后續(xù)I/O無(wú)法發(fā)起怎栽; 解決方案:分解大型運(yùn)算任務(wù)為多個(gè)小任務(wù),使得運(yùn)算能夠適時(shí)釋放宿饱,不阻塞I/O調(diào)用的發(fā)起熏瞄;
2、只支持單核CPU谬以,不能充分利用CPU强饮;
3、可靠性低为黎,一旦代碼某個(gè)環(huán)節(jié)崩潰邮丰,整個(gè)系統(tǒng)都崩潰 原因:?jiǎn)芜M(jìn)程行您,單線程 解決方案: (1)Nnigx反向代理,負(fù)載均衡剪廉,開(kāi)多個(gè)進(jìn)程娃循,綁定多個(gè)端口; (2)開(kāi)多個(gè)進(jìn)程監(jiān)聽(tīng)同一個(gè)端口斗蒋,使用cluster模塊捌斧;
4、開(kāi)源組件庫(kù)質(zhì)量參差不齊泉沾,更新快捞蚂,向下不兼容
5、Debug不方便跷究,錯(cuò)誤沒(méi)有stack trace
總結(jié):nodejs本就是極客追求性能極致的產(chǎn)物姓迅,缺少了很多服務(wù)器的健壯性考量,所以不適用于銀行俊马、證券丁存、電信等需要極高可靠性的業(yè)務(wù)中
6、應(yīng)用場(chǎng)景
nodeJs 善于I/O潭袱,不善于計(jì)算柱嫌,因?yàn)閚odejs最擅長(zhǎng)的就是任務(wù)調(diào)度,如果你的業(yè)務(wù)有巨量的CPU計(jì)算(同步代碼)屯换,實(shí)際上也相當(dāng)于這個(gè)計(jì)算阻塞了整個(gè)線程编丘,即巨量的計(jì)算不適合NodeJS開(kāi)發(fā)。 當(dāng)應(yīng)用程序需要處理大量高并發(fā)的I/O彤悔,而在向客戶端發(fā)出響應(yīng)之前嘉抓,應(yīng)用程序內(nèi)部并不需要復(fù)雜的處理的時(shí)候,NodeJs非常適合晕窑。 適合與 web socket 配合抑片,開(kāi)發(fā)長(zhǎng)連接的實(shí)時(shí)交互應(yīng)用程序。
- RESTful API
這是NodeJS最理想的應(yīng)用場(chǎng)景杨赤,可以處理數(shù)萬(wàn)條連接敞斋,本身沒(méi)有太多的邏輯,只需要請(qǐng)求API疾牲,組織數(shù)據(jù)進(jìn)行返回即可植捎。它本質(zhì)上只是從某個(gè)數(shù)據(jù)庫(kù)中查找一些值并將它們組成一個(gè)響應(yīng)。由于響應(yīng)是少量文本阳柔,入站請(qǐng)求也是少量的文本焰枢,因此流量不高,一臺(tái)機(jī)器甚至也可以處理最繁忙的公司的API需求。
- 統(tǒng)一Web應(yīng)用的UI層
目前MVC的架構(gòu)济锄,在某種意義上來(lái)說(shuō)暑椰,Web開(kāi)發(fā)有兩個(gè)UI層,一個(gè)是在瀏覽器里面我們最終看到的荐绝,另一個(gè)在server端一汽,負(fù)責(zé)生成和拼接頁(yè)面。
不討論這種架構(gòu)是好是壞很泊,但是有另外一種實(shí)踐角虫,面向服務(wù)的架構(gòu)沾谓,更好的做前后端的依賴分離委造。如果所有的關(guān)鍵業(yè)務(wù)邏輯都封裝成REST調(diào)用,就意味著在上層只需要考慮如何用這些REST接口構(gòu)建具體的應(yīng)用均驶。那些后端程序員們根本不操心具體數(shù)據(jù)是如何從一個(gè)頁(yè)面?zhèn)鬟f到另一個(gè)頁(yè)面的昏兆,他們也不用管用戶數(shù)據(jù)更新是通過(guò)Ajax異步獲取的還是通過(guò)刷新頁(yè)面。
- 大量Ajax請(qǐng)求的應(yīng)用
例如個(gè)性化應(yīng)用妇穴,每個(gè)用戶看到的頁(yè)面都不一樣爬虱,緩存失效,需要在頁(yè)面加載的時(shí)候發(fā)起Ajax請(qǐng)求腾它,NodeJS能響應(yīng)大量的并發(fā)請(qǐng)求跑筝。 總而言之瞒滴,NodeJS適合運(yùn)用在高并發(fā)曲梗、I/O密集、少量業(yè)務(wù)邏輯的場(chǎng)景妓忍。
4虏两、具體場(chǎng)景可以表現(xiàn)為如下:
- Web服務(wù) API 如:REST
- 基于web、canvas等多人聯(lián)網(wǎng)游戲
- 后端的web服務(wù)世剖,如:跨域定罢、服務(wù)器端的請(qǐng)求;
- 基于web的多人實(shí)時(shí)聊天客戶端旁瘫、聊天室祖凫、圖文直播
- 高并發(fā)量的web應(yīng)用程序 如:用戶表單收集系統(tǒng)、實(shí)時(shí)交互系統(tǒng)酬凳、考試系統(tǒng)惠况、聯(lián)網(wǎng)軟件
- 單頁(yè)面瀏覽器應(yīng)用程序
二、Nodejs
1粱年、 REPL(交互式解釋器)
Node.js REPL(Read Eval Print Loop:交互式解釋器) 表示一個(gè)電腦的環(huán)境售滤,類(lèi)似 Windows 系統(tǒng)的終端或 Unix/Linux shell,我們可以在終端中輸入命令,并接收系統(tǒng)的響應(yīng)
//啟動(dòng) Node 的終端
node
- ctrl + c - 退出當(dāng)前終端完箩。
- ctrl + c 按下兩次 - 退出 Node REPL赐俗。
- ctrl + d - 退出 Node REPL.
- 向上/向下 鍵 - 查看輸入的歷史命令
- tab 鍵 - 列出當(dāng)前命令
- .help - 列出使用命令
- .break - 退出多行表達(dá)式
- .clear - 退出多行表達(dá)式
- .save filename - 保存當(dāng)前的 Node REPL 會(huì)話到指定文件
- .load filename - 載入當(dāng)前 Node REPL 會(huì)話的文件內(nèi)容。
2弊知、Node.js 全局對(duì)象
2.1阻逮、有唯一的全局對(duì)象 global 2.2、process = global.process process也是Node.js提供的一個(gè)對(duì)象秩彤,它代表當(dāng)前Node.js進(jìn)程
2.3叔扼、判斷JavaScript執(zhí)行環(huán)境
if (typeof(window) === 'undefined') {
console.log('node.js');
} else {
console.log('browser');
}
3、事件循環(huán)
ode.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ì)列開(kāi)頭蓄坏,這個(gè)結(jié)果被返回給用戶价捧。
這個(gè)模型非常高效可擴(kuò)展性非常強(qiáng),因?yàn)?webserver 一直接受請(qǐng)求而不等待任何讀寫(xiě)操作涡戳。(這也稱之為非阻塞式IO或者事件驅(qū)動(dòng)IO)
在事件驅(qū)動(dòng)模型中结蟋,會(huì)生成一個(gè)主循環(huán)來(lái)監(jiān)聽(tīng)事件,當(dāng)檢測(cè)到事件時(shí)觸發(fā)回調(diào)函數(shù)
// 引入 events 模塊
var events = require('events');
// 創(chuàng)建 eventEmitter 對(duì)象
var eventEmitter = new events.EventEmitter();
// 創(chuàng)建事件處理程序
var connectHandler = function connected() {
console.log('連接成功渔彰。');
// 觸發(fā) data_received 事件
eventEmitter.emit('data_received');
}
// 綁定 connection 事件處理程序
eventEmitter.on('connection', connectHandler);
// 使用匿名函數(shù)綁定 data_received 事件
eventEmitter.on('data_received', function(){
console.log('數(shù)據(jù)接收成功嵌屎。');
});
// 觸發(fā) connection 事件
eventEmitter.emit('connection');
console.log("程序執(zhí)行完畢。");
大多數(shù)時(shí)候我們不會(huì)直接使用 EventEmitter胳岂,而是在對(duì)象中繼承它编整。包括 fs、net乳丰、 http 在內(nèi)的掌测,只要是支持事件響應(yīng)的核心模塊都是 EventEmitter 的子類(lèi)
4、模塊(ES6 模塊产园、CommonJS 模塊)
1汞斧、語(yǔ)法上面,CommonJS 模塊使用require()
加載和module.exports
輸出什燕,ES6 模塊使用import
和export
粘勒。
// package.json 文件中,指定type 字段
{
"type": "module"
}
.mjs
文件總是以 ES6 模塊加載屎即,.cjs
文件總是以 CommonJS 模塊加載庙睡,.js
文件的加載取決于package.json
里面type
字段的設(shè)置
4事富、fs
Node.js內(nèi)置的fs
模塊就是文件系統(tǒng)模塊,負(fù)責(zé)讀寫(xiě)文件乘陪。
和所有其它JavaScript模塊不同的是统台,fs
模塊同時(shí)提供了異步和同步的方法
// 異步讀取文件
'use strict';
var fs = require('fs');
fs.readFile('sample.txt', 'utf-8', function (err, data) {
if (err) {
console.log(err);
} else {
console.log(data);
}
});
// 同步讀取文件
'use strict';
var fs = require('fs');
var data = fs.readFileSync('sample.txt', 'utf-8');
console.log(data)
5、Stream(流)
stream是Node.js提供的又一個(gè)僅在服務(wù)區(qū)端可用的模塊啡邑,目的是支持“流”這種數(shù)據(jù)結(jié)構(gòu)
Node.js贱勃,Stream 有四種流類(lèi)型:
- Readable - 可讀操作。
- Writable - 可寫(xiě)操作谤逼。
- Duplex - 可讀可寫(xiě)操作.
- Transform - 操作被寫(xiě)入數(shù)據(jù)贵扰,然后讀出結(jié)果。
所有的 Stream 對(duì)象都是 EventEmitter 的實(shí)例流部。常用的事件有:
data - 當(dāng)有數(shù)據(jù)可讀時(shí)觸發(fā)戚绕。
end - 沒(méi)有更多的數(shù)據(jù)可讀時(shí)觸發(fā)。
error - 在接收和寫(xiě)入過(guò)程中發(fā)生錯(cuò)誤時(shí)觸發(fā)贵涵。
-
finish - 所有數(shù)據(jù)已被寫(xiě)入到底層系統(tǒng)時(shí)觸發(fā)列肢。
文件流讀取文本內(nèi)容的示例
'use strict';
var fs = require('fs');
// 打開(kāi)一個(gè)流:
var rs = fs.createReadStream('sample.txt', 'utf-8');
rs.on('data', function (chunk) {
console.log('DATA:')
console.log(chunk);
});
rs.on('end', function () {
console.log('END');
});
rs.on('error', function (err) {
console.log('ERROR: ' + err);
});
6、http模塊
request
對(duì)象封裝了HTTP請(qǐng)求宾茂,我們調(diào)用request
對(duì)象的屬性和方法就可以拿到所有HTTP請(qǐng)求的信息;
response
對(duì)象封裝了HTTP響應(yīng)拴还,我們操作response
對(duì)象的方法跨晴,就可以把HTTP響應(yīng)返回給瀏覽器。
'use strict';
// 導(dǎo)入http模塊:
var http = require('http');
// 創(chuàng)建http server片林,并傳入回調(diào)函數(shù):
var server = http.createServer(function (request, response) {
// 回調(diào)函數(shù)接收request和response對(duì)象,
// 獲得HTTP請(qǐng)求的method和url:
console.log(request.method + ': ' + request.url);
// 將HTTP響應(yīng)200寫(xiě)入response, 同時(shí)設(shè)置Content-Type: text/html:
response.writeHead(200, {'Content-Type': 'text/html'});
// 將HTTP響應(yīng)的HTML內(nèi)容寫(xiě)入response:
response.end('<h1>Hello world!</h1>');
});
// 讓服務(wù)器監(jiān)聽(tīng)8080端口:
server.listen(8080);
console.log('Server is running at http://127.0.0.1:8080/');
7端盆、crypto
crypto模塊的目的是為了提供通用的加密和哈希算法
7.1MD5
MD5是一種常用的哈希算法,用于給任意數(shù)據(jù)一個(gè)“簽名”费封。這個(gè)簽名通常用一個(gè)十六進(jìn)制的字符串表示:
const crypto = require('crypto');
const hash = crypto.createHash('md5');
// 可任意多次調(diào)用update():
hash.update('Hello, world!');
hash.update('Hello, nodejs!');
console.log(hash.digest('hex')); // 7e1977739c748beac0c0fd14fd26a544
7.2焕妙、其他加密算法
Hmac算法也是一種哈希算法,它可以利用MD5或SHA1等哈希算法弓摘。不同的是焚鹊,Hmac還需要一個(gè)密鑰,Hmac理解為用隨機(jī)數(shù)“增強(qiáng)”的哈希算法
AES是一種常用的對(duì)稱加密算法韧献,加解密都用同一個(gè)密鑰
DH算法是一種密鑰交換協(xié)議末患,它可以讓雙方在不泄漏密鑰的情況下協(xié)商出一個(gè)密鑰來(lái)
RSA算法是一種非對(duì)稱加密算法,即由一個(gè)私鑰和一個(gè)公鑰構(gòu)成的密鑰對(duì)锤窑,通過(guò)私鑰加密璧针,公鑰解密,或者通過(guò)公鑰加密渊啰,私鑰解密探橱。其中申屹,公鑰可以公開(kāi),私鑰必須保密隧膏。
8独柑、路由(url)
我們要為路由提供請(qǐng)求的 URL 和其他需要的 GET 及 POST 參數(shù),隨后路由需要根據(jù)這些數(shù)據(jù)來(lái)執(zhí)行相應(yīng)的代碼
https://www.runoob.com/nodejs/nodejs-router.html
9私植、GET/POST請(qǐng)求
https://www.runoob.com/nodejs/node-js-get-post.html
9忌栅、nodejs連接 MySQL
9.1、安裝mysql
cnpm install mysql
連接數(shù)據(jù)庫(kù)曲稼,并執(zhí)行查詢語(yǔ)句
var mysql = require('mysql');
var connection = mysql.createConnection({
host : 'localhost',
user : 'root',
password : '123456',
port: '3306',
database: 'test'
});
connection.connect();
var sql = 'SELECT * FROM websites';
//查
connection.query(sql,function (err, result) {
if(err){
console.log('[SELECT ERROR] - ',err.message);
return;
}
console.log('--------------------------SELECT----------------------------');
console.log(result);
console.log('------------------------------------------------------------\n\n');
});
connection.end();
9.2索绪、connection.query查詢方式
第一個(gè)參數(shù)是一個(gè)SQL語(yǔ)句,可以是任意的數(shù)據(jù)庫(kù)語(yǔ)句贫悄,而第二個(gè)參數(shù)是一個(gè)回調(diào)函數(shù)瑞驱,查詢結(jié)果通過(guò)回調(diào)參數(shù)的方式返回。
connection.query('select * from book where author = "xyf" and country = "china"',function(err, result) {
console.log(result);
}
);
第二種 占位符注入查詢
第二種查詢方式是采用了占位符的形式connection.query(sqlString, values, callback) 窄坦,這樣就不需要進(jìn)行惡心的字符串的拼接了唤反。
connection.query('select * from book where author = ? and country = ?',
['xyf', 'china'],function(err, result) {
console.log(result);
}
);
第三種 使用對(duì)象查詢方式
第三種查詢方式我們將查詢語(yǔ)句和查詢值組合成一個(gè)對(duì)象來(lái)進(jìn)行查詢。它的形式是這樣的:connection.query(object, callback)
connection.query(
{
sql:'select * from book where author = ? and country = ?',
values: ['xyf', 'china'], //作為對(duì)象的屬性
timeout: 40000,},function(err, result) { console.log(result);}
);
10鸭津、REST
REST就是一種設(shè)計(jì)API的模式彤侍,最常用的數(shù)據(jù)格式是JSON
1、REST即表述性狀態(tài)傳遞(英文:Representational State Transfer逆趋,簡(jiǎn)稱REST)是Roy Fielding博士在2000年他的博士論文中提出來(lái)的一種軟件架構(gòu)風(fēng)格
2盏阶、HTTP 方法
以下為 REST 基本架構(gòu)的四個(gè)方法:
- GET - 用于獲取數(shù)據(jù)。
- PUT - 用于更新或添加數(shù)據(jù)闻书。
- DELETE - 用于刪除數(shù)據(jù)名斟。
- POST - 用于添加數(shù)據(jù)。
拓展內(nèi)容
1魄眉、Express(提供了最簡(jiǎn)單而強(qiáng)大的方式來(lái)創(chuàng)建 Web 服務(wù)器砰盐。它的極簡(jiǎn)主義方法、沒(méi)有偏見(jiàn)坑律、專注于服務(wù)器的核心功能岩梳,是其成功的關(guān)鍵)
2、Koa2(Koa 是一個(gè)新的 web 框架脾歇,由 Express 幕后的原班人馬打造蒋腮, 致力于成為 web 應(yīng)用和 API 開(kāi)發(fā)領(lǐng)域中的一個(gè)更小、更富有表現(xiàn)力藕各、更健壯的基石)
3池摧、Egg.js(使用 Node.js 和 Koa 構(gòu)建更好的企業(yè)級(jí)框架和應(yīng)用程序的框架)
4、NestJs(基于 TypeScript 的漸進(jìn)式 Node.js 框架激况,用于構(gòu)建企業(yè)級(jí)的高效作彤、可靠和可擴(kuò)展的服務(wù)器端應(yīng)用程序)
5膘魄、Socket.io (構(gòu)建網(wǎng)絡(luò)應(yīng)用的實(shí)時(shí)通信引擎)
6、js模板引擎(EJS竭讳、Nunjucks)
7创葡、MySql (關(guān)系型數(shù)據(jù)庫(kù)管理系統(tǒng))/ MongoDB(非關(guān)系型數(shù)據(jù)庫(kù))
7.1、數(shù)據(jù)庫(kù)CRUD
# 插入數(shù)據(jù)
INSERT INTO table_name ( field1, field2,...fieldN )
VALUES
( value1, value2,...valueN )
# 查詢數(shù)據(jù)
SELECT column_name,column_name
FROM table_name
[WHERE Clause]
[LIMIT N][ OFFSET M]
# 修改數(shù)據(jù)
UPDATE table_name SET field1=new-value1, field2=new-value2
[WHERE Clause]
# 刪除數(shù)據(jù)
DELETE FROM table_name [WHERE Clause]
# 多表查詢
# tcount_tbl
mysql> SELECT * FROM tcount_tbl;
+---------------+--------------+
| runoob_author | runoob_count |
+---------------+--------------+
| 菜鳥(niǎo)教程 | 10 |
| RUNOOB.COM | 20 |
| Google | 22 |
+---------------+--------------+
# runoob_tbl
mysql> SELECT * from runoob_tbl;
+-----------+---------------+---------------+-----------------+
| runoob_id | runoob_title | runoob_author | submission_date |
+-----------+---------------+---------------+-----------------+
| 1 | 學(xué)習(xí) PHP | 菜鳥(niǎo)教程 | 2017-04-12 |
| 2 | 學(xué)習(xí) MySQL | 菜鳥(niǎo)教程 | 2017-04-12 |
| 3 | 學(xué)習(xí) Java | RUNOOB.COM | 2015-05-01 |
| 4 | 學(xué)習(xí) Python | RUNOOB.COM | 2016-03-06 |
| 5 | 學(xué)習(xí) C | FK | 2017-04-05 |
+-----------+---------------+---------------+-----------------+
INNER JOIN(內(nèi)連接,或等值連接):獲取兩個(gè)表中字段匹配關(guān)系的記錄绢慢。 INNER JOIN 中 INNER可以省略
mysql> SELECT a.runoob_id, a.runoob_author, b.runoob_count FROM runoob_tbl a INNER JOIN tcount_tbl b ON a.runoob_author = b.runoob_author;
+-------------+-----------------+----------------+
| a.runoob_id | a.runoob_author | b.runoob_count |
+-------------+-----------------+----------------+
| 1 | 菜鳥(niǎo)教程 | 10 |
| 2 | 菜鳥(niǎo)教程 | 10 |
| 3 | RUNOOB.COM | 20 |
| 4 | RUNOOB.COM | 20 |
+-------------+-----------------+----------------+
LEFT JOIN(左連接):獲取左表所有記錄灿渴,即使右表沒(méi)有對(duì)應(yīng)匹配的記錄。
mysql> SELECT a.runoob_id, a.runoob_author, b.runoob_count FROM runoob_tbl a LEFT JOIN tcount_tbl b ON a.runoob_author = b.runoob_author;
+-------------+-----------------+----------------+
| a.runoob_id | a.runoob_author | b.runoob_count |
+-------------+-----------------+----------------+
| 1 | 菜鳥(niǎo)教程 | 10 |
| 2 | 菜鳥(niǎo)教程 | 10 |
| 3 | RUNOOB.COM | 20 |
| 4 | RUNOOB.COM | 20 |
| 5 | FK | NULL |
+-------------+-----------------+----------------+
RIGHT JOIN(右連接): 與 LEFT JOIN 相反胰舆,用于獲取右表所有記錄骚露,即使左表沒(méi)有對(duì)應(yīng)匹配的記錄
mysql> SELECT a.runoob_id, a.runoob_author, b.runoob_count FROM runoob_tbl a RIGHT JOIN tcount_tbl b ON a.runoob_author = b.runoob_author;
+-------------+-----------------+----------------+
| a.runoob_id | a.runoob_author | b.runoob_count |
+-------------+-----------------+----------------+
| 1 | 菜鳥(niǎo)教程 | 10 |
| 2 | 菜鳥(niǎo)教程 | 10 |
| 3 | RUNOOB.COM | 20 |
| 4 | RUNOOB.COM | 20 |
| NULL | NULL | 22 |
+-------------+-----------------+----------------+
# 子查詢(相關(guān)子查詢和非相關(guān)子查詢)
嵌套在其他查詢中的查詢即子查詢,子查詢也叫內(nèi)部查詢缚窿,子查詢總是從內(nèi)向外處理棘幸。
SELECT * FROM tab1 WHERE size IN (
SELECT size FROM tab2
)
相關(guān)子查詢:指查詢結(jié)果依賴于外部查詢的子查詢,外部查詢每執(zhí)行一次倦零,內(nèi)部子查詢也會(huì)執(zhí)行一次
非相關(guān)子查詢:指獨(dú)立于外部查詢的子查詢误续,內(nèi)部子查詢僅執(zhí)行一次,執(zhí)行完畢后將查詢結(jié)果作為外部查詢的條件使用
不依賴與外部的查詢
非相關(guān)子查詢一般可以分為:
返回單值的子查詢
返回一個(gè)列表的子查詢
# MySQL中數(shù)據(jù)的基本查詢方式
1.查詢所有列
select * from 表名稱;
2.查詢指定列
select 字段名扫茅,字段名蹋嵌,字段名 from 表名稱;
3.查詢時(shí)添加常量列(臨時(shí)備注)
select 字段名,字段名诞帐,字段名欣尼,字段名 as 備注 from 表名稱;
4.查詢時(shí)合并列(合并列只能合并數(shù)值類(lèi)型的字段)
select 字段名,(字段名+字段名) from 表名稱;
5.查詢時(shí)去除重復(fù)記錄
select distinct 字段名 from 表名稱;
6.條件查詢(where)
(1)邏輯條件:and(并) or(或)
select * from 表名稱 where 字段名=值 and 字段名=值;
select * from 表名稱 where 字段名=值 or 字段名=值;
⊥=丁(2)比較條件:> < >= <= = <>(不等于) between and(等價(jià)于>=且<=)
(3)判空條件(null空字符串):is null / is not null / = ' ' /<> ' '
null:表示沒(méi)有值 / 空字符串:有值钙态,但是值是空字符串
判斷null
select * from 表名稱 where 字段名 is null慧起;
判斷空字符串
select * from 表名稱 where 字段名=' ';
判斷null和空字符串
select * from 表名稱 where 字段名 is null or 字段名=' ';
查詢不包括null和空字符串的字段
select * from 表名稱 where 字段名 is not null and 字段名<> ' ';
(4)模糊條件:like
通常用一下替換標(biāo)記:
%:表示任意個(gè)字符
_:表示一個(gè)字符
select * from 表名稱 where 字段名 like '部分值%';
7.聚合查詢(使用聚合函數(shù)的查詢)
常用的聚合函數(shù):sum()求和 avg()求平均值 max()求最大值 min()求最小值 count()計(jì)數(shù)
用法:select 聚合函數(shù)(字段名) from 表名稱;
注意:count()函數(shù)統(tǒng)計(jì)的數(shù)量不包含null的數(shù)據(jù)册倒,使用count統(tǒng)計(jì)表的記錄數(shù)蚓挤,要使用不包含null值的字段。
8. 分頁(yè)查詢(limit起始行驻子,查詢幾行)
起始行從0開(kāi)始
分頁(yè):當(dāng)前頁(yè) 每頁(yè)顯示多少條
分頁(yè)查詢當(dāng)前頁(yè)的數(shù)據(jù)的sql:select * from 表名稱 limit(當(dāng)前頁(yè)-1) 每頁(yè)顯示多少條灿意,每頁(yè)顯示多少條;
例如:查詢第1,2條記錄(第一頁(yè)的數(shù)據(jù))
select * from 表名稱 limit 0,2;(當(dāng)前頁(yè)-1再乘以2,顯示幾條數(shù)據(jù))
查詢第3,4條記錄(第二頁(yè)的數(shù)據(jù))
select * from 表名稱 limit 2,2;
查詢第5,6條記錄(第三頁(yè)的數(shù)據(jù))
select * from 表名稱 limit 4,2;
查詢第7,8條記錄
select * from 表名稱 limit 6,2;
9. 查詢排序(order by)
語(yǔ)法:order by 字段 asc/desc
asc:順序崇呵,正序缤剧。數(shù)值:遞增,字母:自然順序(a-z)
desc:倒序域慷,反序荒辕。數(shù)值:遞減汗销,字母:自然反序(z-a)
默認(rèn)情況下,按照插入記錄順序排序
select * from 表名稱 order by 字段名 asc/desc;
注意:多個(gè)排序條件
select * from 表名稱 order by 字段名 asc抵窒,字段名 desc弛针;
10. 分組查詢(group by)
select 字段名(同一個(gè)) from 表名稱 group by 字段名(同一個(gè));
11. 分組查詢后篩選
注意:分組之前條件使用where關(guān)鍵字,分組之后條件使用having關(guān)鍵字,如分組后找出大于或者小于n的字段
select 字段名李皇,count(*) from 表名稱 group by 字段名 having count(*) 比較條件 n;
8削茁、Mocha(一個(gè)功能豐富的javascript測(cè)試框架,運(yùn)行在node.js和瀏覽器中掉房,使異步測(cè)試變得簡(jiǎn)單有趣)
9茧跋、Sequelize(Node的ORM框架Sequelize來(lái)操作數(shù)據(jù)庫(kù))
10、Nunjucks(模板引擎就是基于模板配合數(shù)據(jù)構(gòu)造出字符串輸出的一個(gè)組件)
11圃阳、EJS(高效的嵌入式 JavaScript 模板引擎)