中间件分类
在Express中应用程序可以使用以下类型的中间件:
- 应用程序级别中间件
- 路由级别中间件
- 错误处理中间件
- 内置中间件
- 第三方中间件
1. 应用程序级别中间件
- 不关心请求路径
app.use(function(req, res, next)) {
console.log('Time:', Date.now())
next()
})
- 限定请求路径:
app.use('/user/:id', function(req, res, next) {
console.log('Request type:', req.methods)
next()
})
- 限定请求方法 + 请求路径
app.get('/user/:id', function(req, res, next) {
res.send('USER')
})
- 多个处理函数
app.use('/user/:id', function(req, res, next){
console.log('Request URL', req.originalUrl)
next()
}, function(req, res, next) {
res.send('User info')
})
- 为同一个路径定义多个处理中间件:
app.get("/user/:id", function(req, res, next) {
console.log('ID:', req.params.id)
next()
}, function(req, res, next) {
res.send('user info')
})
app.get('/user/:id', function(req, res, next) {
res.end(req.params.id)
})
- 中间件在数组中声明为可重用
function logOriginalUrl(req, res, next) {
console.log('Request URL:', req.originalUrl)
next()
}
function logMethod(req, res, next) {
console.log('Request Type:', req.method)
next()
}
var logStuff = [logOriginalUrl, logMethod];
app.get('/user/:id', logStuff, function(req, res, next) {
res.send('User info')
})
要从路由器中间件堆栈中跳过其余中间件功能,请调用
next('route')
将控制权传递给下一个路由。 注意:next('route')
仅在使用app.MRTHOD()
或router.METHOD()
函数加载的中间件函数中有效。
2.路由器级中间件
路由器级中间件与应用程序级中间件的工作方式相同,只不过它绑定到的实例express.Router()
var router = express.Router()
使用router.use()
和router.METHOD()
函数加载路由器级中间件
新建router.js,代码如下:
const express = require('express');
const { getDb, saveDb } = require('./db')
// 1.创建路由实例
// 路由实例其实就相当于一个mini Express实例
const router = express.Router()
// 2.配置路由
// 查询任务
router.get('/', async (req, res) => {
try {
let db = await getDb();
res.status(200).json(db.todos);
} catch (err) {
res.status(500).json({
error: err.message
})
}
})
// 查询单个任务
router.get('/:id', async (req, res) => {
try {
let db = await getDb();
let todo = db.todos.find(todo => todo.id.toString() === req.params.id);
if (!todo) {
return res.status(404).json({
data: 'not found'
})
}
res.status(200).json(todo)
} catch {
res.status(500).json({
error: err.message
})
}
})
// 添加任务
router.post('/', async (req, res) => {
try {
// 1. 获取请求体数据
const todo = req.body;
// 2. 验证数据
if (!todo.name) {
return res.status(422).json({
error: 'The file name is required!!'
})
}
// 3。验证通过,将数据存储到db中
const db = await getDb();
const lastTodo = db.todos[db.todos.length - 1];
todo.id = lastTodo ? lastTodo.id + 1 : 1;
db.todos.push(todo)
await saveDb(db)
res.status(200).json(todo)
} catch (err) {
res.status(500).json({
error: err.message
})
}
})
// 修改任务
router.patch('/:id', async (req, res) => {
try {
const id = req.params.id;
const todo = req.body;
if (!todo.name) {
return res.status(422).json({
error: 'The todo name is required!!'
})
}
let db = await getDb()
db.todos.forEach(item => {
if (item.id == id) {
item.name = todo.name
}
});
await saveDb(db)
res.status(200).json({
data: '修改成功'
})
} catch (err) {
res.status(500).json({
error: err.message
})
}
})
// 删除任务
router.delete('/:id', (req, res) => {
res.send(`delete /todos/${req.params.id}`)
})
// 3.导出路由实例
module.exports = router
// 4.将路由怪哉集成到Express实例应用当中
index.js,代码如下:
const express = require('express');
const app = express()
const router = require('./router')
//配置解析表单请求体: ‘application/json’
app.use(express.json())
//配置解析表单请求体:‘application/x-www-form-urlencoded’
app.use(express.urlencoded())
// 挂载路由
// 第一个参数:配置的公共路径
// app.use(router)
app.use('/todos', router)
app.listen(3000, () => {
console.log('server is running!!')
})
3.错误处理级中间件
错误处理中间件必须要定义四个参数,缺一不可。
app.use((err, req, res, next) => {
res.status(500).json({
error: err.message
})
})
如果将任何内容传递给该next()函数(字符串除外‘route’),Express都会将当前请求视为错误,并且将跳过所有剩余的非错误处理路由和中间件函数。 修改之后的代码如下:
router.get('/', async (req, res) => {
try {
let db = await getDb();
res.status(200).json(db.todos);
} catch (err) {
// res.status(500).json({
// error: err.message
// })
next(err)
}
})
404异常处理中间件,代码如下:
const express = require('express');
const app = express()
const router = require('./router')
//配置解析表单请求体: ‘application/json’
app.use(express.json())
//配置解析表单请求体:‘application/x-www-form-urlencoded’
app.use(express.urlencoded())
// 挂载路由
// 第一个参数:配置的公共路径
// app.use(router)
app.use('/todos', router)
// 404异常处理
app.use((req, res, next) => {
res.status(404).send('404 not found.')
})
app.use((err, req, res, next) => {
res.status(500).json({
error: err.message
})
})
app.listen(3000, () => {
console.log('server is running!!')
})
4.内置中间件
express.json()
解析Content-Type为application/json格式的请求体express.urlencoded()
解析Content-Type为application/x-www-form-urlencoded格式的请求体express.raw()
解析Content-Type为application/octet-stream格式的请求体express.text()
解析Content-Type为text/plain格式的请求体express.static()
托管静态资源文件
5.第三方中间件
包括官方的和第三方的中间件,查看官网。