以前講ES6的時候有提過一部分Node的知識,簡單回顧下:一文讀懂ES6javascript
npm國內鏡像:https://npm.taobao.org
html
配置國內源:npm install -g cnpm --registry=https://registry.npm.taobao.org
前端
而後就能夠把cnpm
看成npm
來用了,好比以前的React
組件案例:java
cnpm install react
cnpm install react-dom
cnpm i babel-core@old
卸載安裝的包:npm uninstall -g uuid
用npm
而不是cnpm
node
經常使用參數說明:react
i
是install
的簡寫-g
是安裝到全局環境中(默認是當前目錄)-D
添加爲開發依賴(-D ==> --save-dev
開發環境)-S
添加爲生產依賴(-S ==> --save
生產環境)
cnpm i express -S
eg:cnpm init
以後: jquery
PS:你把依賴包刪了也沒事,執行cnpm i
就會會根據package.json
自動安裝依賴包web
課外閱讀:chrome
npm如何管理依賴包的版本 https://www.jianshu.com/p/1470c5d7b8c3 禁止npm自動升級依賴包以及全部下級依賴包版本的方法 https://www.jianshu.com/p/f481cf9b0817
這個以前也說過,能夠看看:VSCode and NoteBook for JavaScript | NodeJS,簡單說下:express
每次F5運行的時候選一下NodeJS
,或者添加一下調試的配置文件
{
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "啓動程序",
"program": "${workspaceFolder}/${relativeFile}"
}
]
}
nodejs
用法和js
基本同樣,只是多了些服務器的模塊,eg:
若是想同時運行nodejs
和html
再添加下配置就好了,好比:
{
"version": "0.2.0",
"configurations": [
{
"type": "chrome",
"request": "launch",
"name": "Launch Chrome against localhost",
"url": "http://localhost:8080/${relativeFile}",
"webRoot": "${workspaceFolder}"
},
{
"type": "node",
"request": "launch",
"name": "啓動程序",
"program": "${workspaceFolder}/${relativeFile}"
}
]
}
配置完成後:想運行HTML就選擇谷歌瀏覽器
想運行nodejs
的js
文件就選擇啓動程序(如今運行JS文件的時候,F5便可自動切換成node)
${workspaceRoot}
VS Code當前打開的文件夾${file}
當前打開的文件${relativeFile}
相對於workspaceRoot
的相對路徑${fileBasename}
當前打開文件的文件名${fileDirname}
所在的文件夾,是絕對路徑${fileExtname}
當前打開文件的擴展名ijavascript
依賴於Python2.7
,詳細過程:Jupyter NoteBook IJavaScript 配置
# 若是nodejs和npm沒安裝能夠先安裝下
sudo apt-get install nodejs npm
# 把ijavascript安裝到全局環境中
sudo npm install -g ijavascript
# 安裝
ijsinstall
而後就和Python同樣用了:
這塊官方文檔寫的很詳細,我就簡單說說,後面用到再詳細說
中文文檔:http://nodejs.cn/api
文檔:http://nodejs.cn/api/http.html
or https://nodejs.org/api/http.html
NodeJS既然做爲服務器,那得先有個服務器的樣子,咱們來個簡單的案例:
node // ES6語法:import http from "http"; (如今還沒能徹底支持) const http = require("http") // 建立一個服務器 let server = http.createServer((request, response) => { // 每次請求都會執行這個方法 console.log(request.url); response.write("<h1>Test NodeJS</h>"); response.end() // 告訴瀏覽器響應結束 }); // 服務器啓動並監聽指定端口 server.listen(8080); // 這個和其餘語言不同,直接監聽對應的端口
效果:
其餘內容須要結合其餘模塊一塊兒講解
文檔:http://nodejs.cn/api/fs.html
or https://nodejs.org/api/fs.html
這個是IO對應的模塊,推薦使用異步方法,簡單看看:(xxxFileSync
是同步方式,不建議使用)
const fs = require("fs");
// 文件讀取
fs.readFile("test.txt",(ex,data) => {
// 若是文件不存在就輸出錯誤信息
if(ex){
console.log(ex);
}else{
console.log(data.toString());
}
});
console.log("[ReadFile異步驗證]我出現就是異步");
// 建立一個文件
fs.writeFile("test.txt","文本內容",ex => {
if(ex){
// 出錯就輸出info
console.log(ex);
}
});
console.log("[WriteFile異步驗證]我出現就是異步");
// 文件追加
fs.appendFile("test.txt","追加內容",ex => {
if(ex){
// 出錯就輸出info
console.log(ex);
}
});
console.log("[AppendFile異步驗證]我出現就是異步");
// 如今再讀着看看
fs.readFile("test.txt",(ex,data) => {
// 若是文件不存在就輸出錯誤信息
if(ex){
console.log(ex);
}else{
console.log(data.toString());
}
});
PS:若是文件不是文本文件,就不能toString
了(data
默認是buffer
類型)
node fs.readFile("知識星球.png", (ex, data) => { if (ex) { console.log("讀取錯誤:", ex); } else { console.log(data); // 看看buffer是啥樣的 fs.writeFile("test.png", data, ex => { if (ex) { console.log("複製錯誤:", ex); } }); } });
效果:
<Buffer 89 50 4e 47 0d 0a 1a 0a 00 00 00 0d 49 48 44 52 00 00 02 10 00 00 02 61 08 06 00 00 00 10 7e 89 ed 00 00 20 00 49 44 41 54 78 01 ec bd 07 98 64 57 79 ... >
圖片照常打開:
簡單小結一下:
fs.readFile("xxx", (ex, data) => { });
fs.writeFile("xxx", data, ex => {});
fs.appendFile("xxx", data, ex => {});
data
是buffer
類型,內置了:
toString()
:buffer轉換成字符串toJSON()
:buffer轉化成Json// 看個案例
data = { "name": "小明", "age": "23" };
fs.writeFile("to.txt", data, ex => {
if (ex) {
console.log(ex);
}
});
fs.readFile("to.txt", (ex, data) => {
if (ex) {
console.log(ex);
} else {
console.log(data);
console.log(data.toJSON());
console.log(data.toString());
console.log(data.toLocaleString());
}
});
上面幾個方法(eg:readFile
)都是先把數據都緩存到內存中,而後纔回調,這樣比較浪費內存,對於大文件不友好,so ==> 流走起
用法比較簡單,看個案例:
node const fs = require("fs"); let rs = fs.createReadStream("知識星球.png"); let ws = fs.createWriteStream("test.png"); // 能夠這麼理解,rs是水龍頭防水的地方,寫反了也就出不了水了 rs.pipe(ws); // 建立一個管道,流從r端到w端
還有一些相似於監聽的事件:
node const fs = require("fs"); let rs = fs.createReadStream("知識星球.png"); let ws = fs.createWriteStream("test.png"); rs.pipe(ws); // 建立一個管道,流從r端到w端 // 能夠理解爲錯誤觸發的事件 rs.on("error", ex => { console.log("讀取失敗", ex); }); rs.on("end", () => { console.log("讀取完成"); }); ws.on("error", ex => { console.log("寫入失敗", ex); }); // 注意,寫入流完成不叫end ws.on("finish", () => { console.log("寫入完成"); });
文檔:http://nodejs.cn/api/url.html
or https://nodejs.org/api/url.html
說url
模塊以前得先說下querystring
模塊
文檔:http://nodejs.cn/api/querystring.html
or https://nodejs.org/api/querystring.html
這個是專門針對參數進行解析的,來個案例:
const querystring = require("querystring");
let jd_qs = "keyword=空氣淨化器&enc=utf-8&qrst=1&rt=1&stop=1&vt=2&psort=3&stock=1&wtype=1&cod=1&click=2";
// 咋一看,好像挺方便,可是有坑:看下一個demo
let str = querystring.parse(jd_qs);
console.log(str)
// 用戶請求通常都是相似於這樣的
let jd_url = "https://search.jd.com/Search?keyword=空氣淨化器&enc=utf-8&qrst=1&rt=1&stop=1&vt=2&psort=3&stock=1&wtype=1&cod=1&click=2";
// querystring.parse 只是對?後面(不包括`?`)的參數進行解析(以`=`和`&`分隔)
str = querystring.parse(jd_url);
console.log(str);
const url = require("url");
// port=null說明是默認端口(http:80,https:443)
let jd_url = "https://search.jd.com/Search?keyword=空氣淨化器&enc=utf-8&qrst=1&rt=1&stop=1&vt=2&psort=3&stock=1&wtype=1&cod=1&click=2";
let str = url.parse(jd_url);
console.log(str); // 發現query並無解析
// 想要解析`query`,能夠多傳一個參數
str = url.parse(jd_url, true);
console.log(str); // 對query解析
PS:通常都是這麼用的:
node // {a, b} = {a:21,b=34,c=22} 只要對應便可解包,若是想取別名可使用:{a:xx, b} = {...} let { pathname, query } = url.parse(request.url, true);
結合上面的HTTP模塊
,來個簡單的web服務器
:
node const fs = require("fs"); const url = require("url"); const http = require("http"); // 建立服務 let server = http.createServer((request, response) => { // 請求 // {a, b} = {a:21,b=34,c=22} 只要對應便可解包,若是想取別名可使用:{a:xx, b} = {...} let { pathname, query } = url.parse(request.url, true); console.log(query, pathname); // 讀取對應文件 fs.readFile(`www${pathname}`, (ex, data) => { if (ex) { // 返回404狀態碼,並設置編碼爲UTF-8 response.writeHeader(404, { "Content-Type": "text/html;charset=utf-8" }); // 提示須要在 writeHeader 以後,否則訪問的是瀏覽器404頁面 response.write("<h1>訪問的頁面不存在~</h1>"); } else { response.write(data); } // 響應結束 response.end(); }); }); // 服務器啓動並監聽指定端口 server.listen(8080);
輸出:(www
目錄就兩個文件,一個test.html
,一個test.png
)
推薦寫法:
node const fs = require("fs"); const url = require("url"); const http = require("http"); let server = http.createServer((request, response) => { let { pathname } = url.parse(request.url, true); console.log(pathname); let rs = fs.createReadStream(`www${pathname}`); // `request`和`response`就是一個典型的讀寫流(`ReadStream`、`WriteStream`) rs.pipe(response); // 讀取失敗 ==> 404 rs.on("error", ex => { response.writeHeader(404); response.write("404 Not Found"); response.end(); }); }); server.listen(8080);
PS:request
和response
就是一個典型的讀寫流(ReadStream
、WriteStream
)
文檔:http://nodejs.cn/api/zlib.html
or https://nodejs.org/api/zlib.html
先看個案例:(zlib
是讀寫流)
node const fs = require("fs"); const zlib = require("zlib"); // 讀寫流 let gz = zlib.createGzip(); // 讀流 let rs =fs.createReadStream("./www/jquery-2.1.1.js"); // 寫流 let ws =fs.createWriteStream("test.js.gz"); // 能夠這麼理解:(gz是讀寫流) // rs水龍頭先傳給了gz,gz又當一個水龍頭傳給了ws rs.pipe(gz).pipe(ws); ws.on("finish",()=>{ console.log("寫入完畢"); });
效果:
結合上面再來個增強版:
node const fs = require("fs"); const zlib = require("zlib"); const http = require("http"); let server = http.createServer((request, response) => { // let { pathname } = url.parse(request.url); console.log(request.url); let rs = fs.createReadStream(`www${request.url}`); let gz = zlib.createGzip(); // 響應以前告訴瀏覽器是gzip的格式 response.setHeader("Content-Encoding", "gzip"); // 返回gzip壓縮後的文件 rs.pipe(gz).pipe(response); // 讀取失敗,404錯誤 rs.on("error", ex => { response.removeHeader("Content-Encoding"); // 返回404狀態碼,並設置編碼爲UTF-8 response.writeHeader(404, { "Content-Type": "text/html;charset=utf-8" }); // 提示須要在 writeHeader 以後,否則訪問的是瀏覽器404頁面 response.write("<h2>您訪問的頁面不存在~</h2>"); response.end(); }); }); server.listen(8080, () => { console.log("服務器啓動成功,端口:8080"); });
輸出對比:
文檔:http://nodejs.cn/api/path.html
or https://nodejs.org/api/path.html
這個主要是針對路徑的模塊,看個案例:path.parse()
const path = require("path");
let file_name = "./images/png/小明.png";
// 文件路徑 ./images/png
console.log(path.dirname(file_name));
// 提取出用 `/` 隔開的 `path` 的最後一部分
// 小明.png
console.log(path.basename(file_name));
// 文件後綴 .png
console.log(path.extname(file_name));
// 文件信息 {root: "", dir: "./images/png", base: "小明.png", ext: ".png", name: "小明"}
console.log(path.parse(file_name)); // 這個常常使用
// ------------------------------
// 當前文件所在文件夾絕對路徑
console.log(path.resolve());
// 文件的絕對路徑
console.log(path.resolve(file_name));
// 能夠看看path的完整信息
console.log(path);
文檔:http://nodejs.cn/api/crypto.html
or https://nodejs.org/api/crypto.html
這塊主要就是用來加密(簽名)的,很簡單:
const cypto = require("crypto");
let obj = cypto.createHash("md5");
// // PS:分屢次提交也同樣:
// obj.update("123");
// obj.update("456");
obj.update("123456");
// e10adc3949ba59abbe56e057f20f883e
console.log(obj.digest("hex"));
let obj2 = cypto.createHash("sha1");
obj2.update("123456");
// 7c4a8d09ca3762af61e59520943dc26494f8941b
console.log(obj2.digest("hex"));
let obj3 = cypto.createHash("sha256");
obj3.update("123456");
// 8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92
console.log(obj3.digest("hex"));
const os = require("os");
// cup核數
console.log(os.cpus().length);
// 輸出我老電腦CPU詳細信息
console.log(os.cpus());
能夠參考我以前講的Python多進程進行對比學習:http://www.javashuo.com/article/p-hjlukftr-d.html
node const os = require("os"); const process = require("process"); const cluster = require("cluster"); // 主進程:分配任務 if (cluster.isMaster) { console.log(`主進程PID:${process.pid}`); for (let i = 0; i < os.cpus().length; i++) { cluster.fork(); } } else { // 子進程執行任務 console.log(`當前進程PID:${process.pid},父進程PPID:${process.ppid}`); }
輸出:
主進程PID:20680 當前進程PID:20620,父進程PPID:20680 當前進程PID:23340,父進程PPID:20680 當前進程PID:11644,父進程PPID:20680 當前進程PID:22144,父進程PPID:20680
node const os = require("os"); const http = require("http"); const process = require("process"); const cluster = require("cluster"); // 主進程:分配任務 if (cluster.isMaster) { console.log(`主進程PID:${process.pid}`); for (let i = 0; i < os.cpus().length; i++) { cluster.fork(); } } else { // 子進程執行任務 http.createServer((request, response) => { console.log(`當前進程PID:${process.pid},父進程PPID:${process.ppid}`); response.write("Fork Test"); response.end(); }).listen(8080, () => { console.log(`服務器啓動成功,當前端口:8080,進程PID:${process.pid}`); }); }
輸出:
PS:NodeJS注意下面幾地方:
這個是第三方模塊,若是沒安裝:
cnpm init
cnpm i uuid -D
(開發環境) or cnpm i uuid -S
(生產環境)
使用案例:
node const uuid = require("uuid/v4"); let uid = uuid(); console.log(uid);
輸出:
65334387-110e-489a-b4c5-cb19cb3875d0