Node
一、什麼是Node
Node是以基於Chrome V8引擎的JavaScript執行環境,使用了一個事件驅動、非阻塞式I/O模型(I/O是 input/output的縮寫,即輸入輸出埠,在傳統的程式設計模式中,I/O操作阻塞了程式碼的執行,極大的降低了程式的效率),Node的出現讓JavaScript 執行在服務端的開發平臺,具有相當重要的意義
二、初識Node
1、路徑
node通過ch
切換路徑到檔案路徑,node的工作路徑如果不切換會導致操作的失敗d:
可以切換碟符,通過ch
切換到工作檔案
2、命令獲取路徑
在Node中,可以通過node命令來獲取相對路徑
*__dirname: 可以獲取到當前js檔案所屬的目錄的絕對路徑.*
*__filename: 可以獲取當前js檔案的絕對路徑.*
3、引入內建path模組
const fs = require('fs');
const path = require('path');
const fullPath = path.join(__dirname, '/data');
console.log(fullPath);
fs.writeFile(fullPath, '麼麼噠!', 'utf-8', err=>{
if(err) return console.log(err);
console.log('yes yyds!!!');
});
4、Buffer
因為JavaScript語言自身只有字串資料型別,沒有二進位制資料型別,但在處理TCP流或檔案流時必須使用二進位制資料,所以Node.js定義了一個專門存放二進位制資料的快取區Buffer,在讀取檔案時,返回data資料時Buffer型別,所以需要轉換為字串
fs.readFile('./data/1.txt',(err, data) => {
if(err){
return console.log('讀取發生錯誤:'+err);
}
console.log( data.toString());
});
三、http模組
http的簡單圖解
const http = require('http');
//建立1個服務
const server = http.createServer((request, response) => {
response.end('Hello, Node.js!');
});
//監聽服務
server.listen(3000, () => console.log('服務啟動成功'));
1、示例-獲取URL讀取檔案的內容
const http = require('http');
const fs = require('fs');
const path = require('path');
const server = http.createServer((req, res) => {
//1.將url 和 method 轉換為小寫
req.url = req.url.toLowerCase();
req.method = req.method.toLowerCase();
const fullPath = path.join(__dirname, 'www', req.url);
fs.readFile(fullPath, (err, data) => {
if(err){
//讀取檔案發生錯誤了. 路徑錯了.
res.statusCode = 404;
res.end();
}else{
res.end(data);
}
});
});
server.listen(80, ()=>console.log('服務正在監聽'));
2、createServer的回撥
1.執行時機:只要有來自客戶端的HTTP請求,這個函式就會被執行
2.回撥函式的兩個引數
req物件,客戶端向服務端發的資料都被封裝在req物件中
req.url 可以獲取請求時候的url及其引數
req.method 可以獲取客戶端請求服務端的方法,post/delete/put/patch/head等
res物件,客戶端響應給服務端的資料全部被封裝在其中,
res.setHeader(),響應資料新增響應頭,通過Content-Type可以返回指定資料的型別
3、請求分為兩部分
請求頭,鍵值對,作用是告訴瀏覽器一些關鍵的資訊
請求體,發給伺服器的資料
4、響應分為兩部分
響應頭 鍵值對 作用: 瀏覽器會根據響應頭中的資料可能會做出一些處理.
響應體 伺服器真正返回給瀏覽器的資料. 瀏覽器會解析響應體中的資料.
響應資料
res.write() 向響應體中寫入資料
res.end(); 結束響應寫入的資料.
5、常見狀態碼
常見狀態碼:
200: 伺服器處理請求成功
201: 處理成功 並且建立了新的資源
400: 瀏覽器傳送給伺服器的資料有問題, 一般都是引數傳遞錯誤.
127.0.0.1/api/joke?num=10
401: 身份驗證過期.或者沒有驗證.
403: 許可權不足.
404: 資源不存在.
500: 伺服器內部發生錯誤.
四、npm使用
1、初始化
npm init -y //儲存了初始化專案的資訊
package.json
其中dependencies: 記錄了我們下載的外掛和版本.
其中scripts屬性.
我們可以將一些常用的命令儲存在 package.json中的scripts屬性中,
npm run xxx; 就可以執行對應的命令.(webstorm不需要,?)
2、下載包
npm install 包名@版本號
3、刪除包
npm uninstall 包名
五、express模組
1 express物件.
這個物件中就有一些方法.
static
2 Application物件.
其實就是我們建立的應用.
3 Request物件
回撥函式中的 第1個引數 req
4 Response物件
回撥函式中的 第2個引數 res
5 Router物件
路由物件.
const express = require('express');//引入
//建立express應用(服務)
const app = express();
app.get(path,(req,res)=>{res.send()})
app.post(path,(req,res)=>{res.send()})
app.use()//
app.use('/api/student', stuRouter);//註冊路由
app.use(express.urlencoded({extended: false}));//註冊中介軟體
app.use(express.static('public'));//靜態頁面託管
req.query
req.body//設定中介軟體之後再使用
1、express模組的檔案讀取和寫入(轉換)
//讀取本地檔案生成五條隨機資料
app.get('/api/v2/joke', (req, res) => {
//從jokes.json檔案中隨機的取1條笑話.
fs.readFile(path.join(__dirname, 'data/jokes.json'), 'utf-8', (err, data) => {
if (err) {
//發生錯誤. 500
return res.status(500).send({
code: 500,
msg: '伺服器內部發生錯誤'
});
}
//讀取的時候,沒有發生錯誤.
// 將讀取出來的資料轉換為一個陣列. 讀取出來的資料是1個字串.
const jokes = JSON.parse(data); // 8880
//隨機5個.
// 產生5個隨機的下標.
const retunJokes = [];
const set = new Set();
while(set.size != 5){
//產生的下標不能重複.
const index = Math.floor(Math.random() * jokes.length);
set.add(index);
}
//執行到這裡,就代表set中儲存了5個不重複的下標.
// set 14 98 5412 27 49
for(let index of set){
retunJokes.push(jokes[index]);
}
res.send({
code: 200,
count: jokes.length,
joke: retunJokes
});
});
});
app.listen(80, () => console.log('服務啟動成功'));
2、express託管靜態頁面
//引入第三方模組
const express = require('express');
//呼叫服務
const app = express();
app.use(express.static(path.join(__dirname, 'public')));
//127.0.0.1/static/index.html
//app.use('/static', express.static('public'));
app.listen(80, ()=>console.log('服務啟動成功'));
六、module
module.export和exports都是Node中的頂層物件,但是為了避免混淆,用module.exports完全足夠,它預設是返回一個空物件,並且讓其他的檔案在引入的時候也可以進行使用,讓各個檔案之間有了聯絡
七、CommonJS規範
CommonJS規範是JavaScript的一種模組化規範,它規定了JavaScript如何進行分模組。而Node.js的模組化是遵循CommonJS規範.
模組化:
如果將所有的程式碼都寫在1個檔案中
- 難以維護
- 不利於團隊開發.
將專案分為一個一個的模組,按照功能
不要把所有的程式碼寫在同1個檔案中,而是將程式碼按照功能分開 分開在一個一個的單獨的模組中
分為三個模組
1、內建模組
2、檔案模組
readFile: 非同步讀取檔案
writeFile: 非同步寫入檔案.
使用require
函式一樣可以載入檔案模組。
3、第三方模組:本質是檔案模組
八、router模組
1.建立router物件
const express = require('express');
const stuHandler = require('../handler/stuHandler.js');
const router = express.Router();
2.在router物件上註冊路由
router.get('/delete', stuHandler.delete);//第一個引數是對應的url部分路徑,第二個引數是邏輯處理模組對應的程式碼
router.post('/update', stuHandler.update);//第一個引數是對應的url部分路徑,第二個引數是邏輯處理模組對應的程式碼
3.將router物件暴露出去 module.exports
九、邏輯處理模組
這塊程式碼才是檔案的核心部分,書寫了具體的請求處理邏輯
以學生管理系統的刪除功能的程式碼為例
module.exports.delete = (req, res) => {
//1. 獲取瀏覽器傳遞給伺服器的id
const { id } = req.query;
//2. 判斷有沒有這個id 400
if (!id) return res.status(400).send({ code: 400, msg: '引數錯誤' });
//3. 有這個id 就去學生庫中刪除這個id的學員.
//3.1 先從學生庫中讀取出所有的學員
const stus = require(jsonPath);
//3.2 迴圈陣列,判斷陣列中是否有一個學員的id剛好等於傳過來的id
let findIndex = -1;
for (let i = 0; i < stus.length; i++) {
if (stus[i].id == id) {
//將當前遍歷出來的這個學員從陣列中刪除.
findIndex = i;
break;
}
}
//這個是在檔案內的JSON資料讀取和查詢,效率相對比較低,在學習MySQL後可以進一步精簡
//迴圈結束以後,如果findIndex的值是-1 說明id不存在.
if (findIndex == -1) return res.status(404).send({ code: 404, msg: 'id不存在' });
// 說明id存在.
// 先從陣列中將這個元素刪除.
stus.splice(findIndex, 1);
// 這個刪除只是刪除了記憶體中的陣列中的元素. json檔案中的資料是不會變的.
// 將stus陣列的資料重新寫入到json檔案中.
fs.writeFile(path.join(__dirname, jsonPath), JSON.stringify(stus), 'utf-8', err => {
if (err) return res.status(500).send({ code: 500, msg: err });
res.send({ code: 200, msg: '刪除成功' });
});
}