理解koa中间件

在了解什么是中间件以前,咱们先实现一个带路由的koa应用。node

实现一个koa路由

要新建一个带路由的koa应用特别容易,跟着个人步骤,几分钟就能完成。
首先,咱们打开命令行,新建一个koa-middleware目录,进入这个目录。npm

mkdir koa-middleware
cd koa-middleware/
复制代码

而后,初始化package.json文件,执行init命令以后一路回车就ok。以后安装咱们须要用到的koa和koa-router依赖。json

npm init
npm i koa koa-router --save
复制代码

而后新建一个app.js文件,这个文件是应用的入口,在这里编写代码浏览器

// app.js

const Koa = require('koa');
const router = require('koa-router')();
const app = new Koa();

router.get('/', async (ctx) => {

    ctx.body = "这是首页";
})
router.get('/userCenter', async (ctx) => {

    ctx.body = '这是一个用户页面';
})

app.use(router.routes());
app.listen(3000);
复制代码
node app
复制代码

以后打开命令行,执行node app命令,打开浏览器访问localhost:3000,就能够看到咱们的页面,改变url,就能够切换页面,这样咱们的路由功能就实现了。bash

什么是koa中间件

koa中间件指的是,匹配路由以前或者以后作的一系列操做。在上面这个例子里,router.get这个函数有两个参数,第一个参数就是匹配的路径,第二个参数是一个函数。在这个函数里,咱们返回了一个body是“这是首页”的页面。这就是咱们匹配路由以后作的操做,也就是中间件。在中间件里咱们能够作不少事情,好比:app

  • 执行任何代码
  • 修改请求和响应对象
  • 利用next()函数调用下一个中间件

中间件也分几种类型,他们分别是:koa

  • 应用级中间件
  • 路由级中间件
  • 错误处理中间件
  • 第三方中间件

应用级中间件

假设咱们如今有这么一个需求,在全部的路由里都打印出当前的时间。咱们能够选择每一个路由单独写一个方法来打印日期,但这是不可取的。这时咱们能够用中间件来写。async

const Koa = require('koa');
const router = require('koa-router')();
const app = new Koa();

// 用于在每次匹配路由前都打印一次当前时间的中间件
app.use(async (ctx,next)=>{
    console.log(new Date());
    await next();// 继续向下匹配
})

router.get('/', async (ctx) => {

    ctx.body = "这是首页";
})
router.get('/userCenter', async (ctx) => {

    ctx.body = '这是一个用户页面';
})

app.use(router.routes());
app.listen(3000);
复制代码

这时,咱们每切换一次url,就能够在控制台打印一次当前时间(注意是控制台打印,不是浏览器)。
这就是应用级中间件,写法是app.use(),注意必须调用next()方法,才会有后续的匹配路由,否则页面就会返回404。函数

路由级中间件

应用级中间件是匹配全部的路由,即无论访问哪一个路由以前,都会调用一次。那么若是咱们只想在访问某个路由以前作一些操做,该怎么办呢?这里咱们用到的是路由级中间件,代码以下:学习

const Koa = require('koa');
const router = require('koa-router')();
const app = new Koa();

router.get('/',async(ctx,next)=>{
    console.log('这是首页');
    await next();
})

router.get('/', async (ctx) => {

    ctx.body = "这是首页";
})

router.get('/userCenter', async (ctx) => {

    ctx.body = '这是一个用户页面';
})

app.use(router.routes());
app.listen(3000);
复制代码

能够看到,咱们访问了两次首页路由,第一次作了一些操做以后,调用next(),第二次再访问,再作另一些操做。这样就能够访问具体某个路由前作一些操做了。

错误处理中间件

若是用户在浏览器输入了错误的url,浏览器会跳转到404界面,但浏览器自带的界面通常很丑,不够美观,因此咱们要本身设计符合咱们项目主题的404界面,这个时候就要用到错误处理中间件了。

const Koa = require('koa');
const router = require('koa-router')();
const app = new Koa();

app.use(async (ctx, next) => {
    next();
    if (ctx.status == 404) {
        ctx.status = 404; 
        ctx.body = "这是一个很是美观的404页面"
    }
});

router.get('/', async (ctx) => {

    ctx.body = "这是首页";
})

router.get('/userCenter', async (ctx) => {

    ctx.body = '这是一个用户页面';
})

app.use(router.routes());
app.listen(3000);
复制代码

第三方中间件

koa有不少第三方的中间件,好比koa-static,koa-bodyparser等,咱们使用这些第三方中间件的时候,要先下载下来,好比:

npm i koa-static koa-bodyparser --save
复制代码

以后先引入再调用

const static = require('koa-static');
const staticPath = './static'; 
app.use(static(
    path.join( __dirname, staticPath) 
));

const bodyParser = require('koa-bodyparser'); 
app.use(bodyParser());
复制代码

koa中间件的执行顺序

在了解koa中间件执行顺序以前,先来看这样一段代码:

const Koa = require('koa');
const app = new Koa();

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);
    ctx.body = 'hello';
})

app.listen(3000);
复制代码

本觉得执行结果会是1,2,3,4,5,没想到竟然是1,3,5,4,2,这是怎么回事呢? 这就是咱们要说到的koa中间件执行的洋葱模型,以下图:

咱们看到这张图,能够这么理解:

  • 切开洋葱,洋葱的纹路是一圈一圈的,中间件以next()函数分界,next()以前的在洋葱纹路的左边,next()以后的在洋葱纹路的右边。
  • 整个程序的执行流程是从洋葱左边执行到洋葱右边,因此先执行完next()以前的,再执行next()以后的。
  • 执行顺序靠前的中间件,在洋葱模型里的圈越大。执行顺序越靠后的中间件,在洋葱模型里的圈越小。

洋葱模型很是关键,它决定了咱们写的程序的运行顺序,好比咱们要写错误处理中间件,就要把response的部分写到next()函数以后,让他在路由匹配完成以后再执行。

const Koa = require('koa');
const router = require('koa-router')();
const app = new Koa();

app.use(async (ctx, next) => {
    next();
    if (ctx.status == 404) {
        ctx.status = 404; 
        ctx.body = "这是一个很是美观的404页面"
    }
});

router.get('/', async (ctx) => {

    ctx.body = "这是首页";
})

router.get('/userCenter', async (ctx) => {

    ctx.body = '这是一个用户页面';
})

app.use(router.routes());
app.listen(3000);
复制代码

总结

本文从搭建一个带路由的koa应用讲起,以后引出了koa中间件的概念,再介绍了几种经常使用的中间件,最后解释了中间件的执行顺序和洋葱模型,很适合刚了解koa的朋友学习,若是对你有帮助,就分享出去吧。

相关文章
相关标签/搜索