有没有写过Koa中间件,说下中间件原理,介绍下自己写过的中间件

Posted 进阶全栈开发

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了有没有写过Koa中间件,说下中间件原理,介绍下自己写过的中间件相关的知识,希望对你有一定的参考价值。

一、中间件简介

Koa是一个中间件框架,本身没有捆绑任何中间件。本身支持的功能并不多,功能都可以通过中间件拓展实现。通过添加不同的中间件,实现不同的需求,从而构建一个Koa应用。

Koa的中间件就是函数,可以是async函数,或是普通函数,以下是官网的示例:

// async 函数

app.use(async (ctx, next) => {

  const start = Date.now();

  await next();

  const ms = Date.now() - start;

  console.log(`${ctx.method} ${ctx.url} - ${ms}ms`);

});


// 普通函数

app.use((ctx, next) => {

  const start = Date.now();

  return next().then(() => {

    const ms = Date.now() - start;

    console.log(`${ctx.method} ${ctx.url} - ${ms}ms`);

  });

});


中间件可以通过官方维护的仓库查找获取,也可以根据需求编写属于自己的中间件。

二、中间件原理

2.1简单示例

const Koa = require("Koa");

const app = new Koa();


// 最外层的中间件

app.use(async (ctx, next) => {

  await console.log(`第 1 个执行`);

  await next();

  await console.log(`第 8 个执行`);

});


// 第二层中间件

app.use(async (ctx, next) => {

  await console.log(`第 2 个执行`);

  await console.log(`第 3 个执行`);

  await next();

  await console.log(`第 6 个执行`);

  await console.log(`第 7 个执行`);

});


// 最里层的中间件

app.use(async (ctx, next) => {

  await console.log(`第 4 个执行`);

  ctx.body = "Hello world.";

  await console.log(`第 5 个执行`);

});


2.2原理

从上面的示例中可以看出,中间件的执行顺序并不是从头到尾,而是类似于前端的事件流。事件流是先进行事件捕获,到达目标,然后进行事件冒泡。中间件的实现过程也是一样的,先从最外面的中间件开始执行,next()后进入下一个中间件,一路执行到最里面的中间件,然后再从最里面的中间件开始往外执行。
Koa中间件采用的是洋葱圈模型,每次执行下一个中间件传入两个参数ctx和next,参数ctx是由koa传入的封装了request和response的变量,可以通过它访问request和response, next就是进入下—个要执行的中间件。

三、编写自己的中间件

3.1 token验证的中间件

前后端分离开发,我们常采用JWT来进行身份验证,其中token一般放在HTTP请求中的 Header Authorization字段中,每次请求后端都要进行校验,如Java 的 Spring框架可以在过滤器中对token进行统一验证,而Koa则通过编写中间件来实现token验证。

// middleware/token.js

module.exports = options => async (ctx,next){

    try{

        const token = ctx.header.authorization;

        if(token){

            // verify 函数验证token,并获取相关信息

             await verify(token)

        }

        await next();

    }catch (err){

        console.log(err);

    }

}


// app.js

const Koa = require("koa");

const app = new Koa();

const token = require("./middleware/token");

app.use(token());

app.listen(3000, () => {

  console.log("server is running at http://localhost:3000");

});


3.2 log 的中间件

日志模块也是线上不可缺少的一部分,完善的日志系统可以帮助我们迅速地排查出线上的问题。通过Koa中间件,我们可以实现属于自己的日志模块

// middleware/logger.js

const fs = require('fs');

module.exports = (options) => async (ctx,next){

    const startTime = Date.now();

    const requestTime = new Date();

    await next();

    const ms = Date.now - startTime;

    let logout = `${ctx.request.ip}--${requestTime}--${ctx.method}--${ctx.url}--${ms}ms`;

    // 输出日志文件

    fs.appendFileSync('./log.txt',logout + '\n');

}


// app.js

const Koa = require("koa");

const app = new Koa();

const logger = require("./middleware/logger");

app.use(logger());

app.listen(3000, () => {

  console.log("server is running at http://localhost:3000");

});


有个log4js的库非常不错,可以结合log4js等包来记录更详细的日志。


以上是关于有没有写过Koa中间件,说下中间件原理,介绍下自己写过的中间件的主要内容,如果未能解决你的问题,请参考以下文章

阿里网易等19家互联网公司前端面试题汇总

koa2中间件koa和koa-compose源码分析原理

深入解析Koa之核心原理

《Koa.js 设计模式-学习笔记》Koa.js第二本开源电子书完结

Koa 系列 — 如何编写属于自己的 Koa 中间件

Koa中间件(middleware)级联原理