上一篇【node.js 关于express框架使用及其“中间件“概念的理解】讲到了express及其中间件概念,介绍了中间件的堆栈式调用规则。今天来学习如何巧妙利用堆栈式的调用规则,实现常见的后端逻辑。
每个中间件都分为两个调用时序,分别是小夫我要进来了 进入中间件时,退出中间件时。
var middleware = function(req, res, next) {
/*
进入中间件时 运行该部分代码
*/
next(); // 下一层
/*
退出中间件时 运行该部分代码
*/
};
对于请求对象的过滤,一般可以放在【进入中间件时】完成,而需要获取下一层中间件上下文才能进行的操作,最好放在【退出中间件时】进行,听起来可能有点抽象,所以我们下面举几个例子来说明。
在实际编程的时候我们往往会遇到如下的情况:要对请求的参数做各种过滤,打回不合格的请求。这个就是典型的顺序过滤的情况,下图很好的描述了这种过滤机制。
我们通过在【进入中间件时】就判断对应的参数是否合法,如果合法就next,否则直接打回错误信息。比如我们可以判断请求头是否包含某些字段,过滤掉非法请求。
var middleware = function(req, res, next) {
var ka = req.get("Keep-Alive"); // 查看请求头keep-alive字段
if(ka===undefined || ka==null) {
res.end("请求头需要包含Keep-Alive");
} else {
next();
}
};
有时候我们会遇到这种情况:用户A有关联账户B,我们需要获得用户的关联账户B是谁,再获取B用户扣费的额度,然后根据B用户扣费的额度,给予A用户回扣
A用户的数据库操作,基于查询B用户的扣费额度,而B用户的查询,又基于A用户数据库的【关联用户】字段,所以这是一种“依赖型”查询。
普通的顺序结构的中间件无法很好的处理这种逻辑,但是我们可以利用中间件的“堆栈式调用”来完成这种逻辑。下图描述了利用【退出中间件时】这个时序,完成依赖型查询
下面是代码的简单例子
var middleware1 = function(req, res, next) {
var userB = ... // 查询B用户的用户名
req.userB = userB; // 写入上下文
next(); // 下一层中间件 middleware2
var amount = req.amount; // 获取回传的查询到的用户B额度
... // 给A回扣 写数据库
res.end("成功"); // 接口返回结果
};
var middleware2 = function(req, res, next) {
var userB = req.userB; // 上一层传过来的用户名
var amount = ... // 查询用户B扣费额度
req.amount = amount; // 回传用户B的额度
};
值得注意的是,先进入中间件1,才进入中间件2,所以我们在使用express的时候要注意use的顺序:
var express = require('express');
var app = express();
app.use(middleware1);
app.use(middleware2);
app.listen(8080);
注: … 表示数据库的查询的代码,就不细了,懂的都懂
有时候会面临许多分支,跳转到不同的业务逻辑,分配给不同的中间件处理。
我们可以在判断中间件中,在上下文中写入分支编号,然后在接下来的中间件中判断传入的分支编号是否对应即可
var express = require('express');
var app = express();
// 判断中间件
var judge = function(req, res, next) {
// 判断要交给哪个中间件处理
if() {
req.chooseCode = 1;
} else if() {
req.chooseCode = 2;
} else {
req.chooseCode = 3;
}
};
// 分支中间件
var middleware1 = function(req, res, next) {
if(req.chooseCode!=1) {
next();
return;
}
/*
中间件1要执行的操作
*/
};
var middleware2 = function(req, res, next) {
if(req.chooseCode!=2) {
next();
return;
}
/*
中间件2要执行的操作
*/
};
var middleware3 = function(req, res, next) {
if(req.chooseCode!=3) {
next();
return;
}
/*
中间件3要执行的操作
*/
};
// 注册中间件到express
app.use(judge);
app.use(middleware1);
app.use(middleware2);
app.use(middleware3);
app.listen(8080);
中间件能够避免重复造轮子,但是如何处理不同中间件之间的逻辑关系,利用堆栈式调用的特性处理比较复杂的查询问题,或者是复用一个中间件,或者是进行分支的跳转。。。
肯定有更优的解决方案,但是作为初学者我害要继续学习。。。之后如果有更好的解决方案 会更新