Express 中間件
Express 是一個路由和中間件Web框架,其自身的功能很少。Express 應用程序本質上是一系列中間件函數調用。
一.簡介
一個請求發送到服務器,要經歷一個生命週期,服務端要: 監聽請求-解析請求-響應請求,服務器在處理這一過程的時候,有時候就很複雜了,將這些複雜的業務拆開成一個個子部分,子部分就是一個個中間件。對於處理請求來說,在響應發出之前,可以對請求和該級響應做一些操作,並且可以將這個處理結果傳遞給下一個處理步驟
簡單說,Express 的中間件(middleware)就是處理HTTP請求的函數。它最大的特點就是,一箇中間件處理完,再傳遞給下一個中間件。App實例在運行過程中,會調用一系列的中間件。
每個中間件可以從App實例,接收三個參數,依次爲request對象(代表HTTP請求)、response對象(代表HTTP迴應),next回調函數(代表下一個中間件)。每個中間件都可以對HTTP請求(request對象)進行加工,並且決定是否調用next方法,將request對象再傳給下一個中間件。用下圖更形象點:
上圖可以看到,用戶取水的過程,就是一個http請求,然後經過一系列中間件處理,最後得到返回結果的過程.
二.作用
express這樣描述中間件的
1.執行任何代碼。
2.修改請求和響應對象。
3.終結請求-響應循環。
4.調用堆棧中的下一個中間件
三.分類
1.應用級中間件
2.路由級中間件
3.錯誤處理中間件
4.內置中間件
5.第三方中間件
6.自定義中間件
四.使用中間件
1.全局使用
const express = require("express");
const app = express();
/**
* 全局使用,
* 注意點,代碼的順序問題
* app.use 的語法
* app.use(PATH, [...HANDLER])
* - PATH 路徑前綴,默認是 /
* - HANDLER 中間件函數,可以是多個
*/
app.use((req, res, next) => {
console.log(1);
//一定要使用next(),纔會將控制器丟給下箇中間件
next();
}, (req, res, next) => {
console.log(2);
next();
}, (req, res, next) => {
console.log(4);
next();
});
app.get('/', (req, res, next) => {
console.log(3);
res.send("hello");
});
app.listen(3000, () => {
console.log("服務啓動成功");
});
2.全局使用時,必須有前綴條件
/**
* 全局調用中間件,但是有前綴條件
*/
const express = require('express')
const app = express()
//這裏是全局中間件 前綴條件是必須是有/hello的路由
app.use('/hello', (req, res, next) => {
console.log('中間件1')
next()
})
// GET http://localhost:3000/
app.get('/', (req, res) => {
console.log('2')
res.send('hello')
})
// GET http://localhost:3000/hello/world
app.get('/hello/world', (req, res) => {
console.log(3)
res.send('hello 1')
})
app.listen(3000, () => {
console.log('服務啓動成功')
})
3.針對路由,局部調用中間件
/**
* 局部調用中間件(針對某個路由單獨去調用)
*/
const express = require('express')
const app = express()
// 1. 定義一箇中間件函數
const hello = (req, res, next) => {
console.log('hi,大家好,我是渣渣輝')
next()
}
//這裏局部調用
// GET http://localhost:3000/
app.get('/', hello, (req, res) => {
res.send('hello')
})
// GET http://localhost:3000/world
app.get('/world', (req, res) => {
res.send('world')
})
app.listen(3000, () => {
console.log('服務啓動成功')
})
4.自定義中間件
const express = require('express');
const app = express();
// 自定義請求日誌中間件
const logger = (req, res, next) => {
console.log("Request Url:" + req.originalUrl);
console.log("Request Method:" + req.method);
console.log("Request Date:" + new Date().toLocaleString());
// 必須要寫
next();
}
//自定義中間件,程序延遲執行
const setTimer = (timeout = 5000) => {
return (req, res, next) => {
setTimeout(() => {
//延遲timeout執行
console.log(`延遲${timeout}秒執行`);
next();
}, timeout);
}
}
//全局調用中間件
app.use(logger);
app.use(setTimer(2000));
app.get('/hello', (req, res, next) => {
console.log("進入get");
res.send("結束");
});
app.listen(3000, () => {
console.log("服務啓動成功");
});
總結一下,在實際開發中,中間件到底處於什麼作用呢?當一個請求發送到服務器後,它的生命週期是 先收到request(請求),然後服務端處理,處理完了以後發送response(響應)回去而這個服務端處理的過程就有文章可做了,想象一下當業務邏輯複雜的時候,爲了明確和便於維護,需要把處理的事情分一下,分配成幾個部分來做,而每個部分就是一箇中間件.
5.app.use方法
use是express註冊中間件的方法,也就是說凡是調用中間件,必須使用use方法,拿上面的第四點代碼中,可看出,使用了app.use方法,註冊了2箇中間件,收到http請求後,先調用logger的中間件,然後做出相應處理,最後通過next()方法,將控制權傳遞給了第二個中間件.然後繼續執行,如果沒有next(),程序將一直掛起,最後無響應