Koa2 中间件原理解析 —— 看了就会写

Koa2 洋葱模型 —— compose 串联中间件的四种实现 原文出自:https://www.pandashen.com 前言 Koa 是当下主流 NodeJS 框架,以轻量见长,而它中间件机制与相对传统的 Express 支持了异步,所以编码时经常使用 async/await,提高了可读性,使代码变得更优雅,上一篇文章 NodeJS 进阶 —— Koa 源码分析,也对 “洋葱模型” 和实现它的 compose 进行分析,由于个人觉得 compose... 阅读详情

在这里插入图片描述


阅读原文


前言

Koa 2.x 版本是当下最流行的 NodeJS 框架,Koa 2.0 的源码特别精简,不像 Express 封装的功能那么多,所以大部分的功能都是由 Koa 开发团队(同 Express 是一家出品)和社区贡献者针对 Koa 对 NodeJS 的封装特性实现的中间件来提供的,用法非常简单,就是引入中间件,并调用 Koa 的 use 方法使用在对应的位置,这样就可以通过在内部操作 ctx 实现一些功能,我们接下来就讨论常用中间件的实现原理以及我们应该如何开发一个 Koa 中间件供自己和别人使用。


Koa 的洋葱模型介绍

我们本次不对洋葱模型的实现原理进行过多的刨析,主要根据 API 的使用方式及洋葱模型分析中间件是如何工作的。

// 洋葱模型特点
// 引入 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);
    await next();
    console.log(6);
});

// 监听服务
app.listen(3000);

// 1
// 3
// 5
// 6
// 4
// 2

我们知道 Koa 的 use 方法是支持异步的,所以为了保证正常的按照洋葱模型的执行顺序执行代码,需要在调用 next 的时候让代码等待,等待异步结束后再继续向下执行,所以我们在 Koa 中都是建议使用 async/await 的,引入的中间件都是在 use 方法中调用,由此我们可以分析出每一个 Koa 的中间件都是返回一个 async 函数的。


koa-bodyparser 中间件模拟

想要分析 koa-bodyparser 的原理首先需要知道用法和作用,koa-bodyparser 中间件是将我们的 post 请求和表单提交的查询字符串转换成对象,并挂在 ctx.request.body 上,方便我们在其他中间件或接口处取值,使用前需提前安装。

npm install koa koa-bodyparser

koa-bodyparser 具体用法如下:

// koa-bodyparser 的用法
const Koa = require("koa");
const bodyParser = require("koa-bodyparser");

const app = new Koa();

// 使用中间件
app.use(bodyParser());

app.use(async (ctx, next) => {
   
   
    if (ctx.path === "/" && ctx.method === "POST") {
   
   
        // 使用中间件后 ctx.request.body 属性自动加上了 post 请求的数据
        console.log(ctx.request.body);
    }
});

app.listen(3000);

根据用法我们可以看出 koa-bodyparser 中间件引入的其实是一个函数,我们把它放在了 use 中执行,根据 Koa 的特点,我们推断出 koa-bodyparser 的函数执行后应该给我们返回了一个 async 函数,下面是我们模拟实现的代码。

// 文件:my-koa-bodyparser.js
const querystring = require("querystring");

module.exports = function bodyParser() {
   
   
    return async (ctx, next) => {
   
   
        await new Promise((resolve, reject) => {
   
   
            // 存储数据的数组
            let dataArr = [];

            // 接收数据
            ctx.req.on("data", data => dataArr.push(data));

            // 整合数据并使用 Promise 成功
            ctx.req.on("end", () => {
   
   
                // 获取请求数据的类型 json 或表单
                let contentType = ctx.get("Content-Type");

                // 获取数据 Buffer 格式
                let data = Buffer.concat(dataArr).toString();

                if (contentType === "application/x-www-form-urlencoded") {
   
   
                    // 如果是表单提交,则将查询字符串转换成对象赋值给 ctx.request.body
                    ctx.request.body = querystring.parse(data);
                } else if (contentType === "applaction/json") {
   
   
                    // 如果是 json,则将字符串格式的对象转换成对象赋值给 ctx.request.body
                    ctx.request.body = JSON.parse(data);
                }

                // 执行成功的回调
                
koa-uuid:koa uuid中间件 考伊 koa uuid中间件 安装 $ npm install koa - uuid 组态 默认配置 const options = { signed : false , maxAge : 1000 * 60 * 60 * 24 * 365 * 10 , httpOnly : true , } 例 const uuid = require ( 'koa-uuid' ) const Koa = require ( 'koa' ) // options is not reuqire and will be assign const options = { maxAge , e 立即下载

相关推荐

koa-decorator-ts:koa装饰器

koa-decorator-ts Koa装饰器(带有TypeScript) 安装 npm i koa-decorator-ts --save /* or */ yarn add koa-decorator-ts 介绍 此包装是用于koa的装饰器,包括koa-router graohql。 您可以使用装饰器定义路由路径,也可以使用现有的Koa控制器创建graphql解析器 用法 app.js import Koa from 'koa' ; // 1. Import Router import Router from 'koa-decorator-ts/router' ; const app

koa-dec-router:一个ES6装饰器+基于类的路由器,支持继承,覆盖,优先级,自动加载控制器等

koa-dec-router 基于ES6装饰器+类的路由器,支持继承,覆盖,优先级,自动加载控制器等。 在引擎盖下使用 。 安装 npm i koa-dec-router 要么 yarn add koa-dec-router 演示版 app.js import Koa from 'koa' import DecRouter from 'koa-dec-router' const decRouter = DecRouter ( { controllersDir : ` ${ __dirname } /controllers` , before : null , // global

AI 算力基础设施深度系列(一):从容器到 Kubernetes——算力底座的诞生

1. 容器 = Namespace(视图隔离) + Cgroup(资源限制) + Union FS(镜像分层)└── 不是虚拟机!共享内核,接近零开销2. K8S 三大设计哲学:└── 声明式 API + 控制循环 + 可扩展架构3. K8S 架构:└── 控制面 (API Server / etcd / Scheduler / Controller Manager)

warm3snow的博客 534

ESD放电路径分析

当金属外壳接地情况下,大部分外部干扰信号将会通过外壳,外壳到接地点,再由接地点回到干扰信号的地,实现干扰信号的回流,这点不仅仅适用于​ESD,对于其他的RI类干扰,也同样适合。发现内部金属板跟外壳的搭接处存在较多的缝隙点,该缝隙点对于频率较高的信号能够实现较为理想的回流,但是对于频率没有那么高的信号,则较难以实现回流,我们尝试将这些缝隙用铜箔包裹住,充分降低该金属板跟外壳的接触阻抗​。我们分析,路径3其实是不期望的路径,我们最期望的路径是1,或者2的内部金属部件跟外壳良好接触情况下的路径。

domen_pan的博客 2228

告别手动发日报!用n8n+钉钉打造智能报告机器人(含模板下载)

本文详细介绍了如何利用n8n开源工作流自动化平台与钉钉机器人搭建智能日报系统,实现数据自动采集、处理和发送。通过实战步骤和模板下载,帮助用户告别手动处理日报的繁琐,提升工作效率和数据准确性。

h3i4j的博客 857

【时间序列预测算法】——Holt-Winters算法介绍及代码实现

背景 一阶二阶三阶指数平滑方法拟合效果均较好,通过结合数据自然属性,数据自身、趋势变化、季节性,提出了这三个角度的衡量量,可以说,理解起来更自然、更亲切。 公式 一阶: sts_tst​是t时刻对xtx_txt​的估计值,这里只有一个参数α,是数据本身的平滑属性的体现。 二阶: 引入了时间趋势变量btb_tbt​,优化了一下一阶的公式。同时还可以预测t+m时刻的值: 三阶: 又引入了季节性周期描述变量ctc_tct​,优化了一下二阶的公式。同时还可以预测t+m时刻的值: NOTE:ct

BlackValley的博客 1万+

手把手教你学基于 Linux 的 NPU 固件开发-第 10 讲:可靠性设计(RAS)——让系统坚如磐石错误检测、纠正与上报机制(ECC、Parity)

组件推荐保护机制备注HBM/DDRScrubbing必须开启,定期巡检片上 SRAMECC(权重/激活值),Parity(指令)权衡面积与可靠性计算单元ABFT或DMR(关键路径)防止计算逻辑错误片上网络CRC重传保证数据传输完整性系统软件AER 上报CE 监控自动恢复闭环管理,杜绝 SDC运维策略预测性维护Checkpoint变被动为主动核心心法(信任硬件,但必须验证。在纳米尺度下,错误是必然发生的物理现象。

MHD0815的博客 91

TextView部分文字可以被点击的效果。TextView拼接图片,图片可以被点击

今有一需求,就是列表标题后拼接图标,点击图标跳转一个web页; 这里简单做下笔记,以供需要的人参考: //设置部分文字点击事件 ClickableSpan clickableSpan = new ClickableSpan() { @Override public void onClick(View widget) { Toast.makeText(conte...

LXFX1108的专栏 692

[DDR5] 模式寄存器 Mode Register MRR/MRW

模式寄存器用于定义各种操作模式。在初始化过程中,可以通过重新执行MRS命令来更改模式寄存器的内容。

串起点滴 1639

NVIDIA Jetson之交叉编译工具

参考:http://bbs.xfyun.cn/forum.php?mod=viewthread&tid=33630 用TX2做红外热成像仪的识别,厂家不提供源码,只能提供对应版本的SDK,但是需要我们自己提供交叉编译器 由于之前没有做过交叉编译相关工作,对编译工具不太了解,因此查找相关资料学习下 交叉编译知识 一般来说,针对嵌入式平台的开发有两种编译模式:原生编译和交叉编译。原生编...

ZONGXP的博客 8384

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

上一篇: NodeJS 使用 cookie 和 session
下一篇: Express 源码分析及简易封装
Panda Shen
博客等级 码龄10年 18粉丝 50原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值