1 koa应用可以使用一下几种中间件
1 应用级中间件
2 路由级中间件
3 错误处理中间件
4 第三方中间件
应用级中间件
egg: 有如下需求 《匹配路由之前在终端打印日期》
话不多说,上代码
const Koa = require('koa')
const Router = require('koa-router')
const app = new Koa()
const router = new Router()
// 匹配路由之前打印日期
app.use(async(ctx, next) => {
console.log(new Date())
next()
})
router.get('/', (ctx) => {
ctx.body = '首页'
})
router.get('/news', (ctx) => {
ctx.body = '新闻页'
})
app.use(router.routes())
app.use(router.allowedMethods())
app.listen(8032)
匹配到路由/, /new,以及其他未定义的路由之前都会执行app.use中间件方法,打印当前时间戳,然后执行next下一个中间件
路由级中间件
匹配任何路由 如果不写next,这个路由被匹配到了就不会继续向下匹配
const router = new Router()
router.get('/', (ctx) => {
ctx.body = '首页'
})
router.get('/news', async (ctx, next) => {
ctx.body = '新闻页1'
await next()
})
router.get('/news', (ctx) => {
ctx.body = '新闻页2'
})
app.use(router.routes())
app.use(router.allowedMethods())
app.listen(8032)
匹配到/news 页面输出‘新闻页2’ why?
匹配到/news路由之后 执行await 下一个中间件,再次匹配到/news 页面对应输出新闻页2
如果我们去掉第二个news路由,页面对应输出‘新闻页1’
如果我们修改第二个news路由
router.get('/list', (ctx) => {
ctx.body = '列表'
})
页面对应还是输出‘新闻页1’
错误处理中间件
egg: 有如下需求
匹配首页路由输出 首页 打印当前路由
匹配/news 输出 新闻页 打印当前路由
其他路由 输出 404页面
const Koa = require('koa')
const Router = require('koa-router')
const app = new Koa()
const router = new Router()
app.use(async (ctx, next) => {
console.log('我是中间件')
next()
if (ctx.status === 404) {
ctx.status = 404
ctx.body = '404页面'
} else {
console.log(ctx.url)
}
})
router.get('/', (ctx) => {
ctx.body = '首页'
})
router.get('/news', async (ctx, next) => {
ctx.body = '新闻页'
})
app.use(router.routes())
app.use(router.allowedMethods())
app.listen(8032)
第三方中间件
常用的第三方中间页有路由 静态资源 body-parser等,具体内容参考浅析Koa2 基础内容(一)
2 koa中间件执行顺序
洋葱圈模型


const Koa = require('koa')
const Router = require('koa-router')
const app = new Koa()
const router = new Router()
app.use(async (ctx, next) => {
console.log(1)
await next()
console.log(2)
})
app.use(async (ctx, next) => {
console.log(3)
await next()
console.log(4)
})
app.use(async (ctx, next) => {
console.log(5)
await next()
console.log(6)
})
router.get('/', (ctx) => {
ctx.body = '首页'
})
router.get('/news', async (ctx, next) => {
ctx.body = '新闻页'
})
app.use(router.routes())
app.use(router.allowedMethods())
app.listen(8032)
执行顺序 1 3 5 6 4 2
中间件方法都为同步时 next()前面的await可以省略不写。为异步时需要加上
const Koa = require('koa')
const Router = require('koa-router')
const app = new Koa()
const router = new Router()
// 匹配任何路由 如果不写next,这个路由被匹配到了就不会继续向下匹配
app.use(async (ctx, next) => {
console.log(1)
await next()
console.log(2)
})
app.use(async (ctx, next) => {
await next()
return new Promise((resolve,reject) => {
setTimeout(() => {
console.log('3')
resolve('44')
}, 1000)
})
})
app.use(async (ctx, next) => {
console.log(4)
await next()
console.log(5)
})
router.get('/', (ctx) => {
ctx.body = '首页'
})
router.get('/news', async (ctx, next) => {
ctx.body = '新闻页'
})
app.use(router.routes())
app.use(router.allowedMethods())
app.listen(8032)
页面输出1 4 5 3 2