Node.js | express 中介軟體詳解(應用級 | 路由級 | 內建 | 第三方)
持續創作,加速成長!這是我參與「掘金日新計劃 · 10 月更文挑戰」的第14天,點選檢視活動詳情
🧑💼 個人簡介:大三學生,一個不甘平庸的平凡人🍬
👉 你的一鍵三連是我更新的最大動力❤️!
🔽 前言
Express
是一個自身功能極簡,完全是由路由和中介軟體構成一個的 web
開發框架:從本質上來說,一個 Express 應用就是在呼叫各種中介軟體。
中介軟體(Middleware) 是一個函式,它可以訪問請求物件(request object (req
)), 響應物件(response object (res
)), 和 web
應用中處於請求-響應
迴圈流程中的中介軟體,一般被命名為 next
的變數。
javascript
function (req, res, next) {
// 三個引數:req, res, next
console.log('我是一箇中間件')
next()
}
中介軟體的功能包括:
- 執行任何程式碼。
- 修改請求和響應物件。
- 終結請求-響應迴圈。
- 呼叫堆疊中的下一個中介軟體。
如果當前中介軟體沒有終結請求-響應迴圈,則必須呼叫 next()
方法將控制權交給下一個中介軟體,否則請求就會掛起。
Express
應用可使用如下幾種中介軟體:
- 應用級中介軟體
- 路由級中介軟體
- 錯誤處理中介軟體
- 內建中介軟體
- 第三方中介軟體
使用可選的掛載路徑,可在應用級別或路由級別裝載中介軟體。另外,你還可以同時裝載一系列中介軟體函式,從而在一個掛載點上建立一個子中介軟體棧。
1️⃣ 應用級中介軟體
簡單來說,應用級中介軟體就是繫結到應用級別(
app
)上的中介軟體
應用級中介軟體使用 app.use()
和 app.METHOD()
繫結到 app
物件 , 其中, METHOD
是需要處理的 HTTP
請求的方法,例如 get
, put
, post
等等,全部小寫。例如:
```javascript var app = express()
// 不指定掛載路徑,則匹配所有路徑 app.use(function (req, res, next) { console.log('無掛載路徑的應用級中介軟體') next() }) ``` 上邊是一個沒有掛載路徑的應用級中介軟體,應用的每個請求都會執行該中介軟體(函式),即使用者訪問的任何路由都會觸發這個函式的執行。
當然我們也可以去指定應用級中介軟體的掛載路徑:
javascript
// 指定掛載路徑為/home,則只匹配/home
app.use("/home", function (req, res, next) {
console.log("/home路徑的應用級中介軟體");
next();
});
這樣就只有匹配到/home
時,上述中介軟體才會執行。
使用app.METHOD()
掛載多個路由處理函式實際就是指定了掛載路徑的應用級中介軟體的應用:
```javascript var app = express()
// isToken是一箇中間件 const isToken = (req, res, next) => { console.log("我相當於是一箇中間件!"); next() };
// getUser是路由的處理函式,並不是中介軟體 const getUser = (req, res) => { res.send("匹配 / 路徑的get請求"); }
// 使用app.get時指定了/user路徑並掛載了isToken中介軟體,則這裡的isToken就相當於是應用級的中介軟體了
app.get("/user", [isToken], getUser);
``
在[Node.js | 你不知道的 express 路由使用技巧](https://juejin.cn/post/7150682752600244232)一文中我們提到了一個路由多處理函式的應用:
token驗證`,我們現在可以使用應用級中介軟體去改造它一下:
```javascript // 不需要token驗證 app.get("/login", (req, res) => { res.send("登入"); });
// 驗證token的函式(可插拔,可複用的中介軟體) const isToken = (req, res, next) => { // 驗證token是否過期,isVaild代表token是否有效 // 一些操作 const isVaild = true; // 假設驗證通過
if (isVaild) {
// 驗證通過了就呼叫next向下執行
console.log("token驗證通過");
// 如果想要在回撥函式之間傳遞資料,我們可以選擇將資料掛載到res引數上
res.ailjx = "海底燒烤店ai";
next();
} else {
// 返回錯誤
// 這裡res.send後後面的回撥函式就不會再執行了
res.send("token驗證失敗!");
}
};
// app.use用來註冊全域性的應用中介軟體,因為JS程式碼是從上向下執行,所以app.use之後的路由才會受該應用中介軟體(isToken)的影響,所以需要注意這個app.use的使用地方 app.use(isToken) // app.use之前不受isToken影響
// 只有token有效時才生效的介面 app.get("/home", (req, res) => { // 返回資料內容 // res.ailjx:獲取驗證token的函式在res上繫結的資料 res.send("home" + res.ailjx); });
app.get("/user", (req, res) => {
// 返回資料內容
res.send("user");
});
``
對比 [Node.js | 你不知道的 express 路由使用技巧](https://juejin.cn/post/7150682752600244232) 一文中的應用,這裡我們將
isToken這個中介軟體在需要
token驗證的路由**前**,不需要
token驗證的路由**後**使用
app.use**全域性掛載**,這樣就不需要在
/home和
/user中單獨註冊新增
isToken`了。
2️⃣ 路由級中介軟體
路由級中介軟體和應用級中介軟體一樣,只是它繫結的物件為express.Router()
,在Node.js | 你不知道的 express 路由使用技巧 一文中我們已經詳細介紹過,大家可以跳轉檢視,這裡就不再多說啦。
3️⃣ 錯誤處理中介軟體
錯誤處理中介軟體和其他中介軟體定義類似,只是要使用 4 個引數 (err
, req
, res
, next
),比普通的中介軟體多了一個err
引數:
javascript
// 錯誤處理中介軟體:錯誤處理程式
app.use(function (err, req, res, next) {
console.error(err);
// status 設定狀態碼
res.status(404).send("找不到頁面!" + err);
});
錯誤處理中介軟體顧名思義就是捕獲錯誤並進行處理的中介軟體,但需要注意的是,它並不會捕獲未定義的路由!
```javascript const express = require("express"); const app = express();
// 錯誤處理中介軟體:錯誤處理程式 app.use(function (err, req, res, next) { console.error(err); // status 設定狀態碼 res.status(404).send("找不到頁面!" + err); });
app.listen(3000, () => { console.log("express啟動!"); }); ``` 上面的程式碼中我們並沒有去定義任何路由,就只是掛載了一個錯誤處理中介軟體,現在我們啟動該伺服器隨便訪問一個路由:
可以看到我們的錯誤處理中介軟體並沒有執行,那使用者訪問未定義的路由時我們怎麼去捕獲呢?這就可以使用前面說到的應用級中介軟體:
```javascript const express = require("express"); const app = express();
// 定義你的一些路由
// 應用級中介軟體:捕獲未定義的路由 app.use(function (req, res, next) { // status 設定狀態碼 res.status(404).send("找不到頁面!"); });
app.listen(3000, () => { console.log("express啟動!"); }); ```
另一個問題就是,錯誤處理中介軟體在什麼情況下才會執行?
當中間件呼叫next
並向其傳入非route
和router
的引數時,會呼叫錯誤處理中介軟體,next
中的引數會傳入到錯誤處理中介軟體的err
引數。
next
中傳入route
和router
的引數時會略過其他路由回撥函式
注意: 由於JS
程式碼是從上向下執行的,所以錯誤處理中介軟體和上面提到的用來捕獲未定義路由的應用級中介軟體通常是放到程式碼的最下邊(app.listen
之前)
4️⃣ 內建中介軟體
express.static
是 Express
唯一內建的中介軟體。它基於 serve-static
,負責在 Express
應用中託管靜態資源。
每個應用可有多個靜態目錄。
javascript
app.use(express.static('public'))
將靜態資原始檔所在的目錄作為引數傳遞給 express.static
中介軟體就可以提供靜態資原始檔的訪問了。
例如,假設在 public
目錄放置了一個index.html
,我們就可以直接通過http://localhost:3000/index.html
來訪問它:
所有檔案的路徑都是相對於存放目錄的,因此,存放靜態檔案的目錄名不會出現在 URL 中
如果你的靜態資源存放在多個目錄下面,你可以多次呼叫 express.static
中介軟體:
javascript
app.use(express.static('public'))
app.use(express.static('files'))
訪問靜態資原始檔時,express.static
中介軟體會根據目錄新增的順序查詢所需的檔案。
如果你希望所有通過 express.static
訪問的檔案都存放在一個“虛擬(virtual
)”目錄(即目錄根本不存在)下面,可以通過為靜態資源目錄指定一個掛載路徑的方式來實現,如下所示:
javascript
app.use('/static', express.static('public'))
現在,你就可以通過帶有 “/static
” 字首的地址來訪問 public
目錄下面的檔案了:
5️⃣ 第三方中介軟體
Express
還具有很多的第三方中介軟體供我們下載使用,我們只需通過npm
安裝所需功能的中介軟體,並在應用中載入即可(可以在應用級載入,也可以在路由級載入)。
下面的例子安裝並載入了一個解析 cookie
的中介軟體: cookie-parser
安裝:
bash
npm install cookie-parser
載入使用:
```javascript
var express = require('express')
var app = express()
var cookieParser = require('cookie-parser')
// 載入用於解析 cookie 的中介軟體 app.use(cookieParser()) ```
🔼 結語
博主的Node.js從入門到精通專欄正在持續更新中,關注博主訂閱專欄學習Node不迷路!
如果本篇文章對你有所幫助,還請客官一件四連!❤️