美文网首页
Koa中间件的使用和实现原理

Koa中间件的使用和实现原理

作者: 指尖轻敲 | 来源:发表于2023-11-28 20:54 被阅读0次

中间件使用

了解原理之前先来看一下Koa中间件怎么使用

import Koa from 'koa'
import koaBody from 'koa-body'
import checkToken from '@middleware/checkToken'

const app = new Koa()
app.use(koaBody({
    multipart: true,
    formidable: {
        maxFileSize: 50 * 1024 * 1024
    }
))
app.use(checkToken())
app.listen(port, () => {
    console.log('server running')
})

通过Koa实例的use方法,把中间件函数的调用作为参数传递进去(调用的时候可以传递一些参数)。所以中间件函数的返回值是一个函数。Koa会根据use调用中间件的先后顺序执行中间件函数。接下来看一下中间件的实现。

中间件实现

export const checkToken = () => {
  return async (ctx, next) => {
    const { authorization } = ctx.request.headers // 在此中间件之前使用了koa-body中间件
    try {
      const data = await check(authorization)
      ctx.userInfo = data.user_info
    } catch (e) {
      ctx.body = {
        code: -1,
        err: 'token校验失败'
      }
      return
    }
    await next()
  }
}

中间件的返回函数可以接收两个参数,第一个参数是当前请求的上下文,第二个参数可以暂时理解为下一个中间件函数,自己去控制后面中间件的调用时机。可以在最后调用,也可以在调用之后再做其它逻辑处理。类似这样:

xxx // 此中间件逻辑
await next()
xxx // 此中间件逻辑

那么为什么中间函数的返回函数可以接收到这两个参数呢?接下来就需要了解Koa的中间件实现原理了。

中间件原理

先来看一下use方法大概是做了什么(与源码的变量名可能有差异,便于理解):

class Koa{
    constructor (){
        this.middlewares = []
    }
    use(middleware){
        if (typeof middleware !== 'function') throw new TypeError('middleware must be a function!')
        this.middlewares.push(middleware)
        return this
    }
}

校验代码就先忽略掉了,use主要是把中间件函数push到一个队列面,然后返回this是为了链式调用。

另外还需要了解一下Koa的执行流程,从listen开始:

const http = require('http')

listen(){
    const server = http.createServer(this.callback())
    return server.listen(...args)
}

这里使用了node的原生模块http,把接收到的参数直接传递给原生模块的listen方法。重点是传递给createServerthis.callback是什么。查看http模块的api发现crerateServer接收的是一个requestListener请求监听函数。接下来看下callback函数的实现。

callback(){
    const fn = this.compose(this.middlewares) // 关键,中间的执行
    // ... 
    const handleRequest = (req, res) => {
        const ctx = this.createContext(req, res) // 通过createContext把原生的req和res生成ctx上下文对象
        return this.handleRequest(ctx, fn) // 注意:这个handleRequest是类的方法,不是这个局部的方法
    }
    return handleRequest // 返回监听函数
}

上面出现了三个函数,compose、createContext、类上的。先来看下compose:来自koa-compose包。以下是源码:

function compose (middleware) {
    // 一些校验可以忽略
    if (!Array.isArray(middleware)) throw new TypeError('Middleware stack must be an array!')
    for (const fn of middleware) {
        if (typeof fn !== 'function') throw new TypeError('Middleware must be composed of functions!')
    }
    // 这个函数就是返回给handleRequest的主要中间件调用逻辑
    return function (context, next) {
        // ... 删掉一些边界判断,简化一下代码,更清晰
        return dispatch(0)
        function dispatch (i) {
            let fn = middleware[i] // 从队列最开始取出一个中间件函数
            try {
                // 向中间件函数fn中传递两个参数,一个context,第二个是递归下一个中间件
                // 也就是前面编写中间件时的两个参数,ctx和next
                return Promise.resolve(fn(context, dispatch.bind(null, i + 1)))
            } catch (err) {
                return Promise.reject(err)
            }
        }
    }
}

createContext这里不关心,来看handleRequest函数:

handleRequest(ctx, fnMiddleware){
    // ...
    const onerror = err => ctx.onerror(err)
    const handleResponse = () => respond(ctx)
    // ...
    return fnMiddleware(ctx).then(handleResponse).catch(onerror) // 执行上面compose中返回的函数
}

相关的代码大致就这些,通过一个流程图来让整体调用流程更加一目了然吧。


无标题流程图.drawio.png

相关文章

  • 8KOA 静态文件

    静态文件 使用 koa-static 中间件实现静态文件访问 安装中间件 使用中间件 使用 koa-mount 自...

  • 2018 各大公司最近面试题

    阿里 使用过的koa2中间件 koa-body原理 介绍自己写过的中间件 有没有涉及到Cluster 介绍pm2 ...

  • 面试题

    阿里 使用过的koa2中间件 koa-body原理 介绍自己写过的中间件 有没有涉及到Cluster 介绍pm2 ...

  • 2018大厂高级前端面试题汇总

    阿里 使用过的koa2中间件 koa-body原理 介绍自己写过的中间件 有没有涉及到Cluster 介绍pm2 ...

  • 玩转Koa之核心原理分析

    这篇文章主要介绍了玩转Koa之核心原理分析,本文从封装创建应用程序函数、扩展res和req、中间件实现原理、异常处...

  • Koa中间件(middleware)级联原理

    前言 上次看到了koa-compose的代码,今天来说一下koa中间件的级联以及工作原理。 中间件工作原理 初始化...

  • node.js使用EJS

    1、安装 koa-views 和 ejs 2、引入 koa-views 配置中间件 3、Koa 中使用 ejs: ...

  • koa-router模块用法

    koa-router模块 koa必不可少的路由处理中间件,之前使用过koa-route模块,用法和koa-rout...

  • koa-body 获取不到文件的原因

    问题描述:在koa项目中,使用koa-body中间件来实现文件的上传功能,但是通过ctx.request.body...

  • Koa2 入门 Koa-body Koa-router

    Koa 入门 koa需要搭配中间件来做接口更方便,使用Koa-body & Koa-router 首先使用npm下...

网友评论

      本文标题:Koa中间件的使用和实现原理

      本文链接:https://www.haomeiwen.com/subject/owsxgdtx.html