完整代碼: github 倉庫地址
1. 中間件原理: 核心handle方法
express_test.js 文件:
// express 中間件原理
const http = require('http')
const slice = Array.prototype.slice
class LikeExpress {
constructor() {
// 存放中間件的列表
this.routes = {
all: [],
get: [],
post: []
}
}
register(path) {
// 註冊中間件的方法: 判斷第一個參數是不是路由(字符串),
const info = {}
if (typeof path === 'string') {
info.path = path
// 從第二個參數開始轉化成數組
info.stack = slice.call(arguments, 1)
//另一種寫法 :
// info.stack = [...arguments].slice(1)
} else {
info.path = '/'
info.stack = [...arguments]
}
return info
}
use() {
// 將所有參數 都傳入register
const info = this.register.apply(this, arguments)
this.routes.all.push(info)
}
get() {
const info = this.register.apply(this, arguments)
this.routes.get.push(info)
}
post() {
const info = this.register.apply(this, arguments)
this.routes.post.push(info)
}
// 獲取匹配的url
match(method, url) {
let stack = []
if (url === '/favicon.ico') {
return stack
}
let curResult = []
curResult = curResult.concat(this.routes.all)
curResult = curResult.concat(this.routes[method])
curResult.forEach(item => {
if (url.indexOf(item.path) === 0) {
// url = '/api/get-cookie 且 item.path === '/'
// 且 item.path === '/api'
// 且 item.path === '/api/get-cookie'
stack = stack.concat(item.stack)
}
})
return stack
}
// 核心 next 的機制
handle(req, res, stack) {
const next = () => {
// 獲取第一個匹配的中間件
const middleware = stack.shift()
if (middleware) {
// 執行中間件函數
middleware(req, res, next)
}
}
next()
}
callback () {
return (req, res) => {
res.json = (data) => {
res.setHeader('Content-type', 'application/json')
res.end(
JSON.stringify(data)
)
}
const url = req.url
const method = req.method.toLowerCase()
const resultList = this.match(method, url)
this.handle(req, res, resultList)
}
}
listen(...args) {
// 創建http服務 並監聽
const server = http.createServer(this.callback())
server.listen(...args)
}
}
// 工廠函數
module.exports = () => {
return new LikeExpress()
}
2. 使用自行封裝express
test.js文件:
// 測試自定義的express
const express = require('./express_test')
// http請求實例
const app = express()
app.use((req, res, next) => {
console.log("請求開始...",req.url, req.method)
next()
})
app.use((req, res, next) => {
// 假設在處理cookie
console.log("處理 cookie")
req.cookie = {
userId: 'user233'
}
next()
})
app.use('/api',(req, res, next) => {
console.log("處理/api路由")
next()
})
function loginCheck (req, res, next) {
setTimeout(() => {
console.log("模擬登陸成功")
next()
})
}
app.get('/api/get-cookie',loginCheck, (req, res , next) => {
console.log('get /api/get-cookie')
res.json({
error: 0,
data:req.cookie
})
next()
})
app.listen(8233, () => {
console.log("監聽 8233")
})
3. 驗證
運行: node test.js
打開瀏覽器輸入: localhost:8233/api
,
localhost:8233/api/get-cookie
查看控制檯,感受這個流程。