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(),程序将一直挂起,最后无响应