Deno中间件框架开发:从零实现Koa.js风格的洋葱模型 | Deno进阶开发笔记
Deno中间件框架开发从零实现Koa.js风格的洋葱模型 | Deno进阶开发笔记【免费下载链接】deno_note《Deno进阶开发笔记》 (不定时更新) 项目地址: https://gitcode.com/gh_mirrors/de/deno_noteDeno作为新一代JavaScript/TypeScript运行时凭借其安全性、模块化设计和原生TypeScript支持正逐渐成为后端开发的新选择。本文将带你从零开始在Deno环境中实现一个类似Koa.js的中间件框架深入理解洋葱模型的工作原理并掌握Deno生态下的Web开发核心技术。为什么选择Deno开发中间件框架Deno自2020年正式发布以来已经发展成为一个成熟的运行时环境。与Node.js相比它具有以下优势原生TypeScript支持无需额外配置即可直接运行TypeScript代码安全的默认行为所有文件系统和网络访问都需要显式授权内置工具链包含格式化、测试、文档生成等开发工具现代标准库基于最新的Web标准支持Fetch API、Web Streams等这些特性使得Deno特别适合构建轻量级、高性能的Web框架。在本项目中我们将利用Deno的这些优势实现一个简洁而强大的中间件框架。洋葱模型中间件的核心原理中间件是现代Web框架的核心概念而洋葱模型则是Koa.js等框架最具特色的设计。简单来说洋葱模型允许中间件在请求处理前后都执行代码形成层层包裹的处理流程。洋葱模型的优势在于灵活的请求/响应处理中间件可以在请求到达时执行前置操作在响应发送前执行后置操作统一的错误处理异常可以在任何中间件层被捕获和处理模块化组合不同功能可以封装为独立中间件按需组合使用从零实现Deno中间件框架1. 项目结构与准备首先克隆项目仓库并进入工作目录git clone https://gitcode.com/gh_mirrors/de/deno_note cd de/deno_note我们的中间件框架主要包含以下核心文件demo/web/application.ts应用主类负责管理中间件和启动服务demo/web/compose.ts实现洋葱模型的核心函数demo/web/context.ts封装请求/响应上下文2. 实现洋葱模型的核心compose函数compose函数是洋葱模型的核心它负责按顺序执行中间件并控制流程。以下是实现代码export const compose function (middleware: Function[]) { if (!Array.isArray(middleware)) { throw new TypeError(Middleware stack must be an array!); } return function(ctx: object, next?: Function) { let index -1; return dispatch(0); function dispatch(i: number) { if (i index) { return Promise.reject(new Error(next() called multiple times)); } index i; let fn: any middleware[i]; if (i middleware.length) { fn next; } if (!fn) { return Promise.resolve(); } try { return Promise.resolve(fn(ctx, () { return dispatch(i 1); })); } catch (err) { return Promise.reject(err); } } }; }这个函数接收一个中间件数组返回一个函数该函数接收上下文对象和下一个中间件函数。通过递归调用dispatch函数实现中间件的层层调用和回溯。3. 创建Application类管理中间件Application类是框架的入口点负责注册中间件、创建HTTP服务器和处理请求import { Context, SafeContext } from ./context.ts; import { Server } from ./../server/mod.ts; import { compose } from ./compose.ts; class Application { private _middlewares: Function[]; private _server: Server; constructor() { this._middlewares []; this._server new Server(); } public use(fn: Function): void { this._middlewares.push(fn); } public async listen(opts: Deno.ListenOptions, fn: Function) { const that this; const server this._server; server.createServer(async function(ctx: Context) { const middlewares that._middlewares; try { const sctx new SafeContext(ctx); await compose(middlewares)(sctx); const body sctx.res.getBody(); if (!(body typeof body string body.length 0)) { sctx.res.setBody(404 Not Found!); } await ctx.res.flush(); } catch (err) { that._onError(err, ctx); } }); server.listen(opts, fn); } private async _onError(err: Error, ctx: Context) { console.log(err); if (ctx instanceof Context) { ctx.res.setBody(err.stack || Server Error); ctx.res.setStatus(500); await ctx.res.flush(); } else { Deno.exit(1); } } } export { Application };在listen方法中我们创建了HTTP服务器并在请求到来时使用compose函数执行所有注册的中间件。4. 封装请求/响应上下文Context类封装了HTTP请求和响应对象提供了简洁的API供中间件使用// 简化版Context类示例 export class Context { public req: Request; public res: Response; constructor(req: Request, res: Response) { this.req req; this.res res; } // 提供便捷方法 public set status(code: number) { this.res.status code; } public set body(value: string) { this.res.body value; } }使用示例创建第一个Deno中间件应用现在让我们使用刚刚实现的框架创建一个简单的Web应用import { Application } from ./demo/web/application.ts; const app new Application(); // 日志中间件 app.use(async (ctx, next) { const start Date.now(); await next(); const ms Date.now() - start; console.log(${ctx.req.method} ${ctx.req.url} - ${ms}ms); }); // 响应中间件 app.use(async (ctx) { ctx.res.setBody(Hello Deno Middleware!); ctx.res.setStatus(200); }); // 启动服务器 app.listen({ port: 8000 }, () { console.log(Server running on port 8000); });运行这个应用deno run --allow-net demo/web/example.ts访问http://localhost:8000你将看到Hello Deno Middleware!的响应同时控制台会输出请求日志。进阶技巧中间件的高级用法1. 错误处理中间件利用洋葱模型的特性我们可以创建一个全局错误处理中间件app.use(async (ctx, next) { try { await next(); } catch (err) { ctx.res.setStatus(500); ctx.res.setBody(Server Error: ${err.message}); } });2. 路由中间件我们可以实现一个简单的路由中间件根据URL路径分发请求function router() { const routes: { path: string, handler: Function }[] []; return { get(path: string, handler: Function) { routes.push({ path, handler }); }, middleware: async (ctx, next) { const route routes.find(r r.path ctx.req.url); if (route) { await route.handler(ctx); } else { await next(); } } }; } // 使用路由 const r router(); r.get(/hello, async (ctx) { ctx.res.setBody(Hello Router!); }); app.use(r.middleware);3. 静态文件服务中间件实现一个提供静态文件服务的中间件async function staticMiddleware(ctx: any, next: Function) { const publicDir ./demo/web_static/public; const path ctx.req.url / ? /index.html : ctx.req.url; try { const file await Deno.readFile(${publicDir}${path}); ctx.res.setBody(file); // 设置适当的Content-Type // ... } catch { await next(); } } app.use(staticMiddleware);总结与扩展通过本文的学习我们从零开始实现了一个基于Deno的中间件框架深入理解了洋葱模型的工作原理。这个框架虽然简单但包含了现代Web框架的核心思想。你可以通过以下方式扩展这个框架添加更多便捷的上下文方法实现更强大的路由系统支持参数和通配符添加模板引擎支持实现中间件的级联和嵌套Deno生态系统正在快速发展这个中间件框架只是Deno强大能力的一个缩影。希望本文能帮助你更好地理解Deno和中间件架构为你的下一个项目提供灵感项目完整代码可以在demo/web/目录下找到包含了更多高级特性和示例。【免费下载链接】deno_note《Deno进阶开发笔记》 (不定时更新) 项目地址: https://gitcode.com/gh_mirrors/de/deno_note创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

从零上手 scene-editor:开源 web3D 场景编辑器的架构解析与实战指南

从零上手 scene-editor:开源 web3D 场景编辑器的架构解析与实战指南

从零上手 scene-editor:开源 web3D 场景编辑器的架构解析与实战指南 【免费下载链接】scene-editor vis-three框架衍生出的全自定义web3D场景编辑器 项目地址: https://gitcode.com/GitHub_Trending/sc/scene-editor 想给项目快速搭一个可交互的 3D 展示场景…

2026/10/8 12:06:00 阅读更多 →
斯坦福 CS221 人工智能速查表:一张纸看懂 AI 核心模型的复习指南

斯坦福 CS221 人工智能速查表:一张纸看懂 AI 核心模型的复习指南

斯坦福 CS221 人工智能速查表:一张纸看懂 AI 核心模型的复习指南 【免费下载链接】stanford-cs-221-artificial-intelligence VIP cheatsheets for Stanfords CS 221 Artificial Intelligence 项目地址: https://gitcode.com/gh_mirrors/st/stanford-cs-221-artif…

2026/10/2 17:57:47 阅读更多 →
Windows激活总翻车?免费开源工具MAS实测4条路线

Windows激活总翻车?免费开源工具MAS实测4条路线

Windows激活总翻车?免费开源工具MAS实测4条路线 【免费下载链接】Microsoft-Activation-Scripts Open-source Windows and Office activator featuring HWID, Ohook, TSforge, and Online KMS activation methods, along with advanced troubleshooting. 项目地址…

2026/9/29 7:16:17 阅读更多 →

最新新闻

RHEL 8存储管理实战:Stratis与VDO的池化、去重与组合使用

RHEL 8存储管理实战:Stratis与VDO的池化、去重与组合使用

1. 为什么要在RHEL 8上折腾Stratis和VDORHEL 8把存储管理拆成了两条腿走路:一条是Stratis,面向本地磁盘池的"傻瓜式"卷管理;另一条是VDO,面向块设备的"压缩去重"层。很多人第一次听到这两个词的反应是"L…

2026/10/15 11:45:26 阅读更多 →
Kindle Fire Utility刷机实战:驱动、adb与fastboot救砖指南

Kindle Fire Utility刷机实战:驱动、adb与fastboot救砖指南

简介:Kindle Fire Utility v0.9.9刷机工具包是面向Amazon Kindle Fire HD用户的定制与修复工具,主要用于获取root权限、刷入自定义恢复系统以及应对设备无法正常开机等场景。压缩包共43个文件,约18.33MB,包括12个exe主程序和11个d…

2026/10/15 11:45:26 阅读更多 →
context-mode:日志排障与代码阅读的上下文利器

context-mode:日志排障与代码阅读的上下文利器

有一次线上报警,服务内存持续飙升。我翻日志文件,看到上百条孤零零的 OutOfMemoryError ,每一条都长得几乎一样,既看不出是哪条调用链触发的,也看不出当时的线程状态和参数。那会儿我只有一个想法:如果这…

2026/10/15 11:45:26 阅读更多 →
AI时代品牌流量基建:传播易GEO生成式引擎优化服务采购攻略

AI时代品牌流量基建:传播易GEO生成式引擎优化服务采购攻略

随着生成式AI大模型成为用户核心信息获取载体,品牌在AI问答场景中的可见度与可信度,已经成为决定B2B企业采购决策、B2C用户消费选择的核心因素。区别于传统搜索引擎营销,GEO(Generative Engine Optimization,生成式引擎优化)是适配…

2026/10/15 11:45:26 阅读更多 →
MCP协议中context-mode的本质与SQLite FTS5上下文索引实践

MCP协议中context-mode的本质与SQLite FTS5上下文索引实践

1. “context-mode”不是功能开关,而是MCP协议中上下文协商的运行态标识 最近在多个开发场景里反复看到“context-mode”这个词——它既不像传统软件里的“debug mode”或“production mode”那样直白,也不像HTTP头里的 X-Mode 那样有明确语义。我最初…

2026/10/15 11:45:26 阅读更多 →
14B视频世界模型如何实现零样本实时闭环机器人策略

14B视频世界模型如何实现零样本实时闭环机器人策略

1. 从一段标题说起:为什么“视频世界模型”突然成了机器人圈的热词第一次看到“把 14B 视频世界模型变成可实时闭环执行的零样本机器人策略”这个说法时,我脑子里冒出来的第一个念头是:这不就是把“看视频学做事”这件事,从离线训…

2026/10/15 11:44:23 阅读更多 →

日新闻

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

1. 为什么选择容器化方式部署 LoRa 网络服务LoRa 物联网项目落地时,网络服务器是整个链路的核心枢纽。它负责接收网关上报的数据包、完成去重与解密、再把有效载荷分发给上层应用。早期大家习惯把网络服务器直接装在物理机上,依赖一堆系统库和特定版本的…

2026/10/15 0:00:46 阅读更多 →
共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

1. 共享推理服务里,扩缩容到底难在哪做过大模型推理服务部署的人,大概都经历过这样的场景:一个团队共用一套推理集群,A 业务跑的是 7B 的小模型,B 业务跑的是 72B 的大模型,C 业务白天流量高、晚上几乎归零…

2026/10/15 0:00:46 阅读更多 →
Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

1. 引子:一次内核恐慌引发的追查先从一个真实场景说起。某次我给一台老旧的嵌入式设备折腾系统裁减,为了把启动时间压进两秒以内,我手贱地把一串自认为“没用”的 systemd 服务给 disable 了,其中就包括systemd-remount-fs.servic…

2026/10/15 0:00:46 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/14 3:30:28 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/14 16:30:29 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/14 3:29:58 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 0:14:36 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/14 22:45:47 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 9:49:14 阅读更多 →