後端知識點總結——NODE.JS(高等)
1.Node入門:
什麼是: 針對收集運用開闢的平台
主要特徵:
- 基於Google的JavaScript運轉時引擎V8
- 擴大了Node範例類庫: TCP,同步或異步文件治理,HTTP
為何運用Node:
- 可以在效勞器端運轉js: 現有前端團隊可直接介入後端js開闢
js天生支撐非壅塞IO:
IO: 代表統統數據收支遞次的操縱:
包括: 文件讀寫, 數據庫操縱, 收集操縱
題目: 有耽誤
傳統壅塞IO: IO操縱會壅塞當前主線程,直到本次IO操縱完成,才實行後續代碼。
非壅塞IO: 縱然處置懲罰較慢的IO操縱時,主進城依舊能處置懲罰其他請求
Js天生支撐非壅塞: 回調函數=事宜輪迴+回調行列
一切非壅塞的操縱,返回的效果暫時在回調行列中守候
由事宜輪迴,自動順次取回到主遞次中恢復實行
回調行列在主遞次以外存儲回調函數,所以,不會滋擾主遞次實行
非壅塞在Web效勞器中:
一般效勞器端運用: 雖然可完成每一個請求自力線程/歷程, 但假如一個請求中,包括多個壅塞IO操縱(接見數據庫,收集,讀寫硬盤文件),該請求返回的時候就即是一切IO操縱的時候總和——慢
Node效勞器端運用: 不只每一個請求是一個自力的線程,且,每一個請求內的每一個IO操縱,都黑白壅塞的。一個包括多個IO操縱的請求,返回的總相應時候,僅僅即是个中一個時候最長的IO操縱的時候。 Node.js vs javascript: Javascript: 編程言語, 遵照ECMAScript
2種運轉環境:
- 客戶端瀏覽器: 由種種客戶端瀏覽器中的js詮釋器實行
擴大: DOM API 和 BOM API 主要目的是為了操縱網頁內容和瀏覽器窗口 - 自力的js詮釋器:Node.js 運用遞次開闢和運轉的平台
僅支撐ECMAScript
擴大: 種種特地的效勞器模塊: TCP, HTTP, 文件讀寫, MYSQL構建一個簡樸的node運用:
豎立一個新的node項目: 基礎敕令:
mkdir 項目文件夾
cd 項目文件夾
npm init //擔任在當前地點的項目目次下自動天生package.json設置文件
運轉:node 進口文件.js
- 客戶端瀏覽器: 由種種客戶端瀏覽器中的js詮釋器實行
2.module
Node運用都是由模塊構成
模塊就是構造遞次功用的一種文件或文件夾
Node運用採納CommonJS模塊範例
CommonJS劃定:
- 每一個文件就是一個模塊,有本身的作用域——防止全局污染
一個文件內定義的變量,函數,類都是該文件私有,對別的文件默許不可見 - 對象,要領和變量也可以從一個文件/模塊中導出(exports),用在別的文件/模塊中。
實際項目中,都是將種種功用/數據,劃分為差別項目模塊來治理
怎樣定義一個模塊:2步:
- 在模塊/文件中定義營業代碼(對象,class,函數)
- 將內部的功用拋出,用於未來別的js文件挪用
2種狀況:
2.1面向對象的體式格局:
- 定義一種class或一個對象,包裹屬性和功用
將class或對象直接賦值給module.exports
个中: module,指當前模塊對象/當前文件exports是當前module對象的一個屬性 實質上也是一個對象,保留未來要拋出的一切東西 exports是當前模塊對外的唯一接口
以後,只需願望將模塊內部的東西,拋出到外部,供別的文件運用時,都要增加到module.exports上
別的文件要想運用當前模塊的功用,就必需用require引入當前模塊,而require的實質是找模塊的exports.
2.2面向函數的體式格局:
- 在文件中,定義多個零星的要領
- 將多個零星的要領增加到module的exports上
實在,可先將零星的要領,先集合定義在一個對象中,再將全部對象賦值給module.exports屬性
引入模塊: require() 特地擔任加載模塊文件
什麼時候: 只需在另一個js文件中,引入自定義模塊並獵取內容時,都用require
實質: 找到js文件,並實行,返回module.exports對象
優化: 單例形式singleton: 始終保持項目中只要一個對象的實例
模塊的引入和加載也是單例形式: 模塊只在第一次被require時,豎立。以後,緩存在內存中。重複require不會致使重複豎立模塊對象。
強調: 模塊是同步加載:前一個加載完,后一個才最先
強烈建議: 一切require必需集合在頂部
途徑: 以./開首,示意運用相對途徑,相對於當前正在實行劇當地點途徑——不能省略!
以/開首,示意Linux體系根目次——絕對途徑
以自定義變量開首,示意在變量保留的地點下繼承查找
什麼前綴也不加!只寫模塊名: 示意加載一个中心模塊或項目引入的第三方模塊
途徑查找遞次:
/usr/local/lib/node/模塊名.js
/home/user/projects/node_modules/模塊名.js
/home/user/node_modules/模塊名.js
/home/node_modules/模塊名.js
/node_modules/模塊名.js
坑: 簡寫: module.exports.fun=function(){…}
可簡寫為: exports.fun=function(){…}
exports實際上是module.exports的別號
var exports=module.exports;
題目: 給exports賦值,沒法賦值給module.exports
由於exports只是一個變量,暫時保留module.exports的地點值。再次給exports賦任何新值,都致使exports與module.exports各奔前程!
防止: 不要用簡寫exports
3.目次模塊:
什麼時候: 當一個模塊代碼,龐雜到需要進一步細分時,一個模塊,就可以由多個文件構成,保留在一個文件夾里。
怎樣:
- 豎立文件夾,集合保留相干的多個js文件模塊
- 在文件夾中增加一個主模塊(index.js),主模塊中,引入並構造好多個小模塊一同導出
在文件夾中增加package.json文件,个中:
{ "name":"模塊名", "main":"./主模塊相對途徑" }
實在, 假如沒有main以至沒有package.json,也行。
會自動優先找文件夾下的index.js
引入目次模塊: require(“./目次名”)
假如願望直接用目次名援用模塊,不加相對途徑:
將目次放入node_modules文件夾中
npm: 第三方模塊的包治理工具: 查詢,下載
除了中心模塊和自定義當地模塊,node生態體系還供應了大批優良第三方模塊
怎樣:
查詢模塊:
隱約查找: npm search 模塊名
準確查找: npm search /^模塊名$/
假如實際完全形貌: npm search /^模塊名$/ --parseable
裝置模塊: 2個位置:
全局裝置: npm install -g 模塊名
途徑: Linux: /usr/local/lib/node_modulesWindows: C:\Users\用戶名\AppData\Roaming\npm\node_modules
- 項目當地裝置: npm install 模塊名 -save
全局對象:
全局作用域對象不是window,而是global
ECMAScript範例中底本劃定的就是global
在瀏覽器中被window替代
強調: 交互形式: 直接在敕令行中測試node運用,一切全局變量/全局函數自動成為global的成員劇本形式: 經由歷程加載js文件實行node運用,文件內的"全局變量/全局函數",僅當前文件一切,不會成為global的成員——防止了全局污染
console對象:
測試主要手腕: 打樁: 在癥結位置輸出癥結變量的值
輸出文本信息: 瀏覽器中4種輸出,node中合併為2中:
console.log/info() 輸出一般的文本信息
console.error/warn() 輸出毛病信息
實在: console.xxx()都自帶格式化功用
Console.log vs console.error: .error可直接導出到文件日記中怎樣: node xxx.js 2> error-file.log 个中:2>示意輸出流,特地向硬盤文件寫入內容
輸出耗時:
Console.time(“標籤”); //準備,最先!
一般遞次邏輯
Console.timeEnd(“標籤”); //完成! 自動輸出與time之間的時候距離
單位測試:
什麼是: 對遞次中最小的實行單位舉行測試
開闢人員主動對本身的函數實行單位測試
怎樣: console.assert(推斷前提, “毛病提醒”)只要前提不滿足時,才輸出msg
輸出客棧:
console.trace()
- 全局對象: process:
process.platform
process.pid
process.kill(pid);
掌握台輸入輸出:
2步:
- 讓掌握台進入輸入狀況:
process.stdin.resume()
process.stdin.setEncoding(“utf-8”)
- 監聽stdin的data事宜:
在掌握台輸入后,按回車,會觸發stdin的data事宜
process.stdin.on("data",text=>{
process.stdout.write( … text … )
})
掌握台參數:
2步: 1. 定義關聯數組,保留參數名和參數對應的處置懲罰函數
2. 啟動時, process.argv數組可自動取得傳入的一切參數, 依據參數挪用差別的處置懲罰函數
process.argv: [“node.exe”,”xxx.js”,”參數值1″,”參數值2″,…]
高精度計時:
準確到納秒, 長處: 不受體系時候影響
怎樣: 2步: 1. 取得最先的時候戳: var start=process.hrtime();
2. 取得完畢時候戳: var diff=process.hrtime(start);
diff: [秒數, 納秒]
取得秒差: diff[0]+diff[1]/1e9
取得毫秒差: diff[0]*1000+diff[1]/1e6
Vs console.time/timeEnd:
time/timeEnd: 缺: 精度低, 優: 效力高
hrtime: 優: 精度高,且不受體系時候影響
瑕玷: 效力低
非I/O的異步操縱(定時器):
什麼時候: 要實行異步回調時
怎樣:
- setTimeout/setInterval() 將回調函數增加到事宜輪迴的timer階段的行列中守候實行。
Timer階段是事宜輪迴的第一階段
習慣上: setTimeout每每都邑設置ms數 - setImmediate() 將回調函數增加到事宜輪迴的check階段的行列中守候實行。
Check階段比Timer要晚實行
習慣上: 並不設置毫秒數,而是一般的追加到守候行列末端即可。 - process.nextTick() 將回調函數到場nextTickQueue行列守候實行
nextTickQueue不介入事宜輪迴,而是在最先timer之前,就馬上實行nextTickQueue中的回調函數
長處: 不會有耽誤 - 自定義的EventEmiter
5.EventEmitter範例:
Node.js一切異步I/O操縱完成時,都邑發送一個事宜到事宜行列
Node.js中很多對象都邑觸發事宜:
比方: http模塊: 豎立Server對象,監聽http請求
一旦收到一個http請求,則馬上觸發事宜,將處置懲罰函數放入事宜行列
fs模塊: 在每次讀寫完文件時,也會觸發事宜,將處置懲罰函數放入事宜行列
什麼是EventEmitter: 特地封裝事宜監聽和事宜觸發的API的一種範例
一切可以觸發事宜的對象,都是EventEmitter範例的子對象
怎樣讓一個對象可以監聽並觸發事宜:
- 引入events模塊: const events=require(“events”)
- 豎立events.EventEmitter範例的子對象:
var emitter=new events.EventEmitter(); 用on,為對象增加事宜監聽:
emitter.on(“自定義事宜名”,function 處置懲罰函數(參數列表){… 取得參數, 實行操縱 …
})
- 在任何狀況下,運用對象的emit要領,觸髮指定的事宜:
emitter.emit(“自定義事宜名”,參數值,…)
觸發一次后,自動解綁:
emitter.once(“自定義事宜名”,處置懲罰函數)
毛病處置懲罰:
題目: try catch沒法捕捉異步挪用中的毛病
處理: Domain
什麼時候: 只需既願望捕捉主遞次毛病,又願望捕捉異步操縱的毛病時
怎樣:
- 引入domain模塊: const domain=require(“domain”)
- 豎立domain對象: const mpDomain=domain.create();
為domain對象增加error事宜監聽
mpDomain.on(“error”,err=>{console.log("失足啦!"+err);
})
將可以失足的遞次放入mpDomain中運轉:
mpDomain.run(()=>{musicPlayer.emit("play");
})
6.協定:
什麼是: 計算機之間經由歷程收集完成通訊時,事前殺青的一種”商定”
為何: 商定使差別廠商的裝備,差別操縱體系之間,都可根據一致商定,恣意通訊
7.分組交流體式格局:
什麼是: 將大數據分割為一個個叫做包(packet)的較小單位舉行傳輸
8.ISO/OSI模子:
ISO(國際範例化構造)
OSI(開放式通訊體系互聯參考模子)
7層:
- 運用層: 劃定運用遞次中的通訊細節
包括: HTTP FTP TELNET SMTP DNS - 示意層: 擔任數據格式的轉換
- 會話層: 豎立銜接
- 傳輸層: 掌握團體數據傳輸
包括:
TCP(傳輸掌握協定): 牢靠傳輸
優: 牢靠,客戶端和效勞端可雙向通訊
缺: 傳輸效力低
什麼時候: 請求牢靠性時
UDP(用戶數據報協定):
什麼時候: 對牢靠性請求不高,對傳輸效力請求高,且發送小數據(qq, 微信, 在線視頻播放) - 收集層: 將數據分組傳輸到目的地
- 數據鏈路層: 擔任計劃收集合節點間的線路
- 物理層: 擔任經由歷程以太網,藍牙,光纖發送0/1的比特流
9.TCP/IP: 互聯網協定套件
包括: TCP 傳輸掌握協定
IP 互聯網協定
TCP/IP不是ISO範例
TCP/IP 只要四層:
蔑視:
- TCP/IP四層協定,離別對應ISO/OSI中的哪一層: 圖6
- 收集豎立銜接需要3次握手,斷開銜接需要4次握手,離別是:
圖7 - HTTP/1.0 1.1 2.0每次晉級有哪些差別
10.net模塊:
運用net模塊:
- 可豎立基於TCP的客戶端與效勞器端通訊
豎立TCP效勞器:
引入net模塊
運用net.createServer要領豎立效勞端對象server
吸收一個回調函數作為參數:
只需有客戶端銜接到當前效勞端,就自動實行該回調函數
回調函數吸收一個socket參數對象,用於與客戶端通訊
Socket對象: 是客戶端在效勞器端的一個代辦對象
可經由歷程socket和真正的客戶端發送和吸收音訊
Socket對象的data事宜,可監聽客戶端發來的音訊
回調函數中, data參數為音訊的內容
Socket對象的end事宜,可監聽客戶端的斷開
Socket的write要領向客戶端輸出音訊
挪用server的listen要領,綁定到一個端口,監聽客戶端發來的鏈接請求
也吸收一個回調函數參數,但僅在啟動監聽后實行一次
豎立TCP客戶端:
引入net模塊
運用net.connect()要領向效勞器豎立銜接
var client=net.connect(效勞端端口,ip,function(){})
回調函數在銜接豎立后,自動觸發一次
為client的data事宜綁定處置懲罰函數,處置懲罰函數的data參數自動吸收效勞端發來的音訊
為client的end事宜增加處置懲罰函數,當客戶端斷開銜接時實行操縱
在任何位置可用client.write(“音訊內容”)向效勞端發送
在任何位置可用client.end() 斷開與效勞端銜接
11.HTTP模塊:
運用HTTP模塊:
- 完成WEB效勞器,吸收請求並返回相應(替代了apache,tomcat)
- 模仿客戶端向一個指定的WEB效勞器發送請求
豎立HTTP效勞端:
引入HTTP模塊
豎立HTTP效勞端server:
var server=http.createServer(function(req,res){
//只需有請求發送到該效勞器,就自動觸發該回調函數
//个中:
//req對象,封裝了發來的請求信息
//res對象,特地用於向效勞器端返回相應
//res.writeHead(狀況碼,{ 屬性:值, …:… ,…})
//res.write("放入相應主體中")
//res.end()
})
啟動監聽: server.listen(端口,function(){ … })
豎立HTTP請求:
運用http.request()要領豎立一個請求(銜接),取得請求對象req
吸收2個參數:
options對象參數:
host
port
method
path /index.html?page=12
回調函數: 在效勞器端返回相應時實行
參數res: 特地用於取得相應內容(相應頭和相應主體)
HTTP協定劃定: 先發相應頭部 用res.headers取得相應頭部對象,用res.statusCode 取得狀況碼
強調: 相應主題是稍後才發送過來
必需用res.on("data",function(buffer){ … String(buffer) …})
強調: 通常從相應中取得的data,默許都是字符串
req.end()完畢併發送請求。
強調:必需加req.end(),請求才發送出去
http.get()
特地向效勞器端發送get請求
是http.request()的簡化:
- 自動設置method為get;
- 自動調req.end
但依舊需要運用res.on(“data”,function(buffer){ … })來吸收相應主體
分塊:
題目: 假如相應主體過大,一次性傳不過來
處理:
分塊發送和吸收,再拼接,再團體轉換
假如分塊吸收,res.on("data",function(buf){ … })每收到一塊,就會重複觸發。
个中buf,僅是个中一塊罷了
請求文件,保留在當地:
引入fs模塊:
豎立寫入流,指向目的文件: var writable=fs.createWriteStream(“相對途徑”)
運用管道,將寫入流writable銜接到res對象上: res.pipe(writable)
相應頭部: res.writeHead(狀況碼,{ })
許可跨域: “Access-Control-Allow-Origin”:”請求泉源的網站”
指定內容範例:”Content-Type”:”application/json” “text/css”
req對象:
請求頭部: req.headers
請求要領: req.method
請求地點: req.url
url的處置懲罰:
引入url模塊
用url.parse(req.url,true)將req.url字符串轉為對象
个中true,示意將search中的參數也轉為對象屬性
怎樣: var obj=url.parse(req.url, true)
个中: obj.query中保留了一切參數及其值
取得請求參數:
Get: get體式格局的參數都經由歷程url中的search通報
obj=url.parse(req.url,true)
obj.query
Post: post體式格局的參數都是放在請求主體中,沒有在url中
題目:obj.query沒法取得
處理: req.on("data",function(buf){ … })
題目: String(buf)取得的是參數的字符串
處理: querystring模塊
12.https模塊:
題目: http協定是明文的
傷害: 1. 通訊運用明文,內容可以被竊聽
2. 不考證身份,有可以遭受假裝
3. 沒法證實音訊的完全性,音訊有可以被改動
收集嗅探器:
13.處理: https協定
https是更平安的http協定:
- 客戶端和效勞器端的雙向認證
- 完全性搜檢
- 內容加密
https=http+ssl
ssl/tls: ssl 平安套接層,對傳統socket進一步供應平安的庇護
tls 傳輸層平安, 實際上是ssl的繼任者
14.供應三大效勞:
- 客戶端和效勞器端的雙向認證 ——牢靠
- 完全性搜檢 ——完全
- 數據加密 ——機密性
tls/ssl的實行歷程:
15.Step0: 取得效勞器端證書, 3步:
- 在效勞器端天生私鑰
- 用私鑰天生一個證書請求文件
將私鑰和請求文件交給第三方CA,第三方CA經由檢察,會天生並頒布證書給請求的效勞器
證書包括2樣東西: 公鑰+公司的信息
Step1: 客戶端請求https協定的web效勞器
Step2: 效勞器返回證書給客戶端
Step3: 客戶端拿到證書後,將證書交給CA。客戶端應用CA中的公鑰隨機天生本身的私鑰 將私鑰發給效勞器端
Step4: 效勞器端取得客戶端發來的客戶端私鑰
到此,客戶端和效勞器端,具有了雷同的兩個鑰匙
以後,效勞器和客戶端發送的一切音訊,都用兩個雷同的私鑰加密和解密
16.怎樣完成https的web效勞器運用:
- 請求https網站的認證證書:
Step1: 用openssl天生效勞器端私鑰:
openssl genrsa -out d:/privatekey.pem 1024
Step2: 用私鑰天生證書請求文件:
openssl req -new -key d:/privatekey.pem -out d:/certificaterequest.csr
Step3: 用私鑰和證書請求文件配合天生證書文件
openssl x509 -req -in d:/certificaterequest.csr -signkey
d:/privatekey.pem -out d:/certificate.pem
2.運用node的https模塊豎立效勞器
Step1: 引入必需的模塊:
const https=require(“https”);
const fs=require(“fs”);
Step2:讀取效勞器私鑰和證書文件,保留到效勞器遞次的變量中
let privatekey=fs.readFileSync(“d:/privatekey.pem”);
let certificate=fs.readFileSync(“d:/certificate.pem”);
Step3: 用https豎立效勞器端運用遞次,供應私鑰和證書,並定義處置懲罰請求的回調函數
https.createServer(
{
key: privatekey,
cert: certificate
},
(req,res)=>{
res.write(“…”)
res.end();
}
).listen(443)
3.用https模塊向https的效勞器發送請求
毛病: http模塊不支撐向https效勞器發送請求
準確:
var https=require(“https”);
https.get(“https://…”, res=>{
res.on(“data”,buf=>{
buf…
})
})
17.express
什麼是: 基於node的http模塊和第三方的Connect框架的web框架
Connect框架: 特地將林林總總的中間件函數粘合在一同,配合處置懲罰http請求中的req對象
什麼時候: 只需對req對象重複實行多種操縱時,都要用connect構造多个中間件。
怎樣:
Step1: 裝置connect模塊: npm install connect –save
Step2: 引入connect模塊: var connect=require(“connect”)
Step3: 用connect模塊豎立處置懲罰req對象的運用遞次實例var app=connect();
Step4: 向connect模塊的運用遞次實例中增加中間件函數
app.use(function md1(req,res,next){
//加工req對象
… …
next();
})
Step5: connect的運用遞次實例,必需要放入createServer中用於處置懲罰效勞器吸收到的req對象
http.createServer(app)
總結: express是在connect基礎上的進一步封裝和簡化,所以express也是採納中間件組合的體式格局,處置懲罰req對象
裝置express框架: 2種:
- 運用當地express模塊,進可以供應效勞支撐,需要自定義增加龐雜的遞次構造
Step1: npm install –save express
Step2: 引入http和express
const http=require(“http”);
const express=require(“express”);
Step3: 豎立express運用實例對象:
let app=express();
Step4: 為app增加種種處置懲罰中間件函數
app.use(function md(req,res,next){ … …})
Step5: 將app和createServer相連
http.createServer(app).listen(端口號); - 運用腳手架, 簡化天生項目的構造:
Step1: 全局裝置express天生器:
npm install –g express-generator
Step2: 用天生器,天生項目腳手架代碼:
express 項目文件夾名 –e //-e 示意用EJS作為前端頁面模板
強調: 只擔任天生項目代碼,並不擔任下載依靠包
Step3: 為腳手架代碼下載一切依靠包
cd 項目文件夾下
npm install //依據package.json中的依靠項
Step4: 用腳手架代碼啟動nodejs效勞器端運用遞次: npm start
express項目構造:
- ./bin/www.js express項目的啟動文件
package.json中: npm start 時 自動實行 node ./bin/www
2./app.js 對express框架的實例對象的設置
請求: 對express實例對象app的一切設置必需放在一個自力的文件模塊app.js中
然後,在主遞次www.js中引入app.js模塊
3../routes/xxx.js 路由模塊
每一個子功用,都應該集合定義在一個路由模塊文件中
在app.js中引入路由文件模塊,並將路由文件模塊增加到app的中間件列表中,並設置上級途徑
在每一個子路由模塊文件中,豎立路由對象,為路由對象增加差別請求要領和差別子途徑下的處置懲罰函數
強調: 子路由中的相對途徑,都是在上級途徑之下的相對途徑
革新腳手架項目構造:
補充缺失的模塊:
express-session 讓express可以處置懲罰session
connect-flash 強化自動保護session的功用
passport 綜合的用戶考證處理方案( 運用passport模塊,完成qq,微信登錄)
- 在app.js中增加對新模塊的援用:
- 為項目增加mongodb支撐
Step1: 裝置mongoose模塊和promise模塊
mongoose: node js專用的簡化操縱mongodb數據庫的模塊
Step2: 豎立文件夾./config,在文件夾下增加config.js
在config.js中定義對象模塊,保留銜接字符串
module.exports={
db:”mongodb://主機名或ip/數據庫名”}
Step3: 在./config文件夾下豎立mongoose.js,保留豎立銜接對象的代碼:
var config=require(‘./config’),
mongoose=require(‘mongoose’);
設置mongoose的promise屬性,運用當前項目的promise模塊
mongoose.Promise=require(‘promise’);
var db=mongoose.connect(config.db) module.exports=db;
Step4: 依據營業需要,定義mongoose模子對象:
豎立./models文件夾, 在models內為每種營業對象豎立特地的模子文件
3步:
- 引入mongoose,取得Schema範例
- 用Schema豎立UserSchema構造
- 將UserSchema編譯為User模子,並拋出為User模塊
Step5: 回到mongoose.js中,在connect以後,引入User模塊require(‘../models/user.model’);
Step6: 回到app.js中,在路由中間件之前,先請求並初始化mongoose.jsrequire(“./config/mongoose”);