二, Koa 应用可使用如下几种中间件:
应用级中间件
路由级中间件
错误处理中间件
第三方中间件
我们先来看一下应用级中间件, 我们还是按照之前的项目将 App.JS 改为如下:
- // 引入 koa 模块
- var Koa = require('koa');
- var Router = require('koa-router');
- // 实例化
- var App = new Koa();
- var router = new Router();
- // 匹配任何路由, 如果不写 next, 这个路由被匹配到了就不会继续向下匹配
- App.use(async (ctx, next) => {
- console.log("我是一个中间件");
- // 当前路由匹配完成以后继续向下匹配
- await next();
- });
- // 配置路由
- router.get('/', async (ctx) => {
- ctx.body = "首页";
- });
- router.get('/news', async (ctx) => {
- ctx.body = "新闻列页面";
- });
- // 启动路由
- App.use(router.routes());
- App.use(router.allowedMethods());
- App.listen(3000);
我们在匹配路由之前写了一个 App.use(async ()=>{}) 的中间件, 该中间件如果不像 router.get 那样写一个参数 "/" 或 "/news", 那么它将匹配任何一个路由, 且最先匹配, 如果我们在其中写 next() 的话, 则会终止在此, 不再向下陪陪路由, 运行结果如下:
我们在编辑器的控制台看一下输出日志:
接下来我们看一下路由中间件:
// 引入 koa 模块 var Koa = require('koa'); var Router = require('koa-router'); // 实例化 var App = new Koa(); var router = new Router(); // 配置路由 router.get('/', async (ctx, next) => { console.log("控制台打印"); // 当前路由匹配完成以后继续向下匹配 await next(); }); router.get('/', async (ctx) => { ctx.body = "首页"; }); router.get('/news', async (ctx) => { ctx.body = "新闻列页面"; }); // 启动路由 App.use(router.routes()); App.use(router.allowedMethods()); App.listen(3000);
在上面的代码中我们定义了两个 router.get('/', ) 的路由, 第一个我们在控制台输出一句话, 第二个我们想页面输出内容. 如果在第一个里面我们不写 next() 方法的话, 则不会进入第二个里面, 结果如下:
控制台打印结果
接下来我们看一下错误处理中间件:
// 引入 koa 模块 var Koa = require('koa'); var Router = require('koa-router'); // 实例化 var App = new Koa(); var router = new Router(); // 匹配任何路由, 如果不写 next, 这个路由被匹配到了就不会继续向下匹配 App.use(async (ctx,next)=>{ await next(); // 如果页面找不到 if(ctx.status==404){ ctx.status = 404; ctx.body="404 页面" } }); // 配置路由 router.get('/', async (ctx) => { ctx.body = "首页"; }); router.get('/news', async (ctx) => { ctx.body = "新闻列页面"; }); // 启动路由 App.use(router.routes()); App.use(router.allowedMethods()); App.listen(3000);
我们还按之前的应用中间件那样写, 然后在里面做了一个 if 语句判断, 当页面响应时, 会给后端返回一个 status 码, 这个就不在单独说了, 如果这个 status 报 404, 我们知道表示该页面不存在, 那么我们就可以拦截 next() 方法, 输出给前端一个 404 页面, 结果如下:
我们匹配了一个 "/news" 路由, 可以正常显示内容, 如果我们不小心少写一个 "s", 写成了 "new", 结果如下:
在上面的代码中我们是将 if 判断语句放在了 next() 方法之后, 那能不能放在 next() 之前呢? 这个问题我们在下面的 koa 中间件流程控制中再详细说明.
第三方中间件在之后的文章中我们用到了第三方模块时再说.
接下来我么看一下 koa 中的中间件流程控制.
koa 被认为是第二代 node web framework, 它最大的特点就是独特的中间件流程控制, 是一个典型的洋葱模型.
上面的两张图可以很直观的说明 koa 中的中间件流程控制. 我们接下来用代码演示一下:
// 引入 koa 模块 var Koa = require('koa'); var Router = require('koa-router'); // 实例化 var App = new Koa(); var router = new Router(); App.use(async (ctx, next) => { console.log('1, 这是第一个中间件 01'); await next(); console.log('5, 匹配路由完成以后又会返回来执行中间件'); }); App.use(async (ctx, next) => { console.log('2, 这是第二个中间件 02'); await next(); console.log('4, 匹配路由完成以后又会返回来执行中间件'); }); router.get('/', async (ctx) => { console.log('3, 匹配到了 news 这个路由'); ctx.body = "首页"; }); // 启动路由 App.use(router.routes()); App.use(router.allowedMethods()); App.listen(3000);
我们在上面的代码引用了两个应用级的中间件, 分别在 next() 前后输出日志, 当我们访问 localhost:3000/ 时, 我们看一下控制台的输出结果:
从输出打印结果顺序我们可以看出中间件会先逐级处理 request 请求, 然后再返回来逐级处理 response 请求, 这就是我们为什么要将 错误处理中间件 中的 if 判断语句放在 next() 方法之后, 这样就是在路由进入 "/news" 后返回 status = 404 的结果后再进行处理, 如果放在了 next() 方法之前, 则会直接判断 if 语句, 不会再向下匹配 "/news" 路由了. 比如我们的用户登录系统就可以这么用, 当用户输入账号密码后出入后台, 后台在数据库匹配之后再进行处理, 处理之后返回给前端, 就是这么玩的.
来源: https://www.cnblogs.com/weijiutao/p/10690535.html