1、概念
一个请求发送到服务器后,它的生命周期是 先收到request(请求)
,然后服务端处理,处理完了以后发送response(响应)
回去而这个服务端处理的过程就有文章可做了,想象一下当业务逻辑复杂的时候,为了明确和便于维护,需要把处理的事情分一下,分配成几个部分
来做,而每个部分
就是一个中间件
app.use
加载用于处理http请求的middleware(中间件)
,当一个请求来的时候,会依次被这些 middlewares处理
。中间件执行的顺序是你定义的顺序。
2、原理与实现
格式
function middleware(req,res,next){
// 做该干的事
// 做完后调用下一个函数
next(); //next()的位置可以随处可放
}
原理
学习链接:https://www.cnblogs.com/donve/p/10265326.html
https://blog.csdn.net/u013263917/article/details/102674437
3、实践(koa中间件)
koa中ctx使用:
· ctx.req:原生的req对象
· ctx.res:原生的res对象
· ctx.request:koa自己封装的request对象
· ctx.response:koa自己封装的response对象
console.log(ctx.query); //原生中需要经过url.parse(p,true).query才能得到的query对象
console.log(ctx.path); //原生中需要经过url.parse(p).pathname才能得到的路径(url去除query部分)
koa中间件使用方式:
(1)一定会有ctx,next();
(2)next指向下一个中间件
//ctx:上下文,核心对象
//next:将处理的控制权转交给下一个中间件
app.use(async (ctx, next)=>{
//...
await next() //等待下个中间件运行结束,才运行当前中间件的后续代码
//...
})
router.post(’/:id/awards’, validateRechargePlanId(),editRechargePlanAwards());
validateRechargePlanId()
中的next()
指向下个中间件editRechargePlanAwards()
function bindUserNoFilter({ userNoField = 'user_no', userIdField = 'user_id' } = {}) {
return async (ctx, next) => {
const filter = JSON.parse(ctx.query.filter || '{}');
if (filter[userNoField]) {
const user = await getCachedUserInfoByUserNo({ userNo: filter[userNoField] });
if (!user) {
ctx.state.data = {
total: 0, page: ctx.state.paginator.page, pagesize: ctx.state.paginator.pagesize, items: [],
};
return;
}
filter[userIdField] = user.user_id;
delete filter[userNoField];
}
ctx.query.filter = JSON.stringify(filter);
await next();
};
}
//此代码await next();在下面,是先执行代码,再执行下一个中间件
//await next();在上面是先执行中间件,在执行下面的代码
//中间件1中使用中间件2,next传入空的function,防止中间件1的next被重复调用
await setPaginator()(ctx, () => {});