【摘要】 KOA中间件的基本运作原理

示例代码托管在:http://www.github.com/dashnowords/blogs

在中间件系统的实现上,KOA中间件通过async/await来在不同中间件之间交换控制权,工作机制和结构非常相似,建议结合《express中间件系统的基本实现》对比学习,两个框架所基于的语法特性有区别(express使用ES5的回调风格语法,KOA使用ES7的扁平式异步async/await风格语法),但在框架基本原理上是很类似的,只是中间件写法和遍历机制稍有不同。

一. API层

  • 初始化方法

    let middleware = new MiddleWare();
  • 添加中间件函数的方法

    //Fn为被添加的中间件,KOA中间件为async函数
    middleware.use(Fn);
  • 预处理中间件栈

    //将存储于数组中的各个中间件组合为按照“先进后出”原则执行的中间件系统。
    middleware.start = middleware.compose();
  • 启动中间件队列

    middleware.start(ctx);

二. 核心类的定义

/*
* KOA中间件框架的基本实现
*/class MiddleWare {constructor(){this.queue = []}//添加中间件函数use(fn){this.queue.push(fn);}//合并中间件处理流,是一个高阶函数,调用一次后会生成真正需要的函数。compose(){return function (ctx, next) {let _this= this;let index = -1;return dispatch(0);/*** KOA中间件的工作的步进函数*/function dispatch(i) {index = i;//依次取用数组中添加的中间件函数let fn = i === _this.queue.length ? next : _this.queue[i];if(!fn){return Promise.resolve();}try{/**中间件函数的形式为 async fn(ctx, next),可以看到此处透传了ctx的引用,*同时next是一个延迟执行中间件队列中下一个中间件的函数,也就是说如果在前*一个中间件的函数体中调用 await next(),就会启动下一个中间件,实际执行*的函数是dispatch(i+1)。*/return Promise.resolve(fn(ctx,()=>{return dispatch(i+1);}));}catch(err){return Promise.reject(err);}}}}
}

三. 使用use方法添加中间件

//添加回调函数
middleware.use(async function(ctx, next){console.log('step 001');ctx.info = 'go through middleware1';await next();console.log('step 006');
});middleware.use(async function(ctx, next){console.log('step 002');await next();console.log('step 005');
});middleware.use(async function(ctx, next){console.log('step 003');await next();console.log('step 004');
});

四. 中间件实例

//初始化
let middleware = new MiddleWare();/*
...此处为添加中间件的代码
*/middleware.start = middleware.compose();

五. 查看运行结果

可以看到有错误发生和正常响应时的不同结果:

六. 在服务器端运行

node起一个web服务器那真是太随意了~

//启动http服务
http.createServer(function(req, res){console.log(req.url);let info = {};middleware.start(info);res.end(JSON.stringify(info));
}).listen(9527);

看一下效果(访问服务器时自定义消息就可以传至前台了):

作者:大史不说话

【nodejs原理源码赏析(2)】KOA中间件的基本运作原理相关推荐

  1. 【nodejs原理源码赏析(1)】Express中间件系统的基本实现

    一直觉得express的中间件系统这种流式处理非常形象,就好像加工流水线一样,每个环节都在针对同一个产品的不同部分完成自己的工作,最后得到一个成品.今天就来实现一个简易的[中间件队列]. 一. API ...

  2. 【nodejs原理源码赏析(6)】深度剖析cluster模块源码与node.js多进程(下)

    目录 一. 引言 二.server.listen方法 三.cluster._getServer( )方法 四.跨进程通讯工具方法Utils 五.act:queryServer消息 六.轮询调度Roun ...

  3. 【nodejs原理源码赏析(5)】net模块与通讯的实现

    [摘要] Node.js net模块的原理及使用 示例代码托管在:http://www.github.com/dashnowords/blogs 一. net模块简介 net模块是nodejs通讯功能 ...

  4. 【nodejs原理源码赏析(4)】深度剖析cluster模块源码与node.js多进程(上)

    [摘要] 集群管理模块cluster浅析 示例代码托管在:http://www.github.com/dashnowords/blogs 一. 概述 cluster模块是node.js中用于实现和管理 ...

  5. 【nodejs原理源码赏析(9)】用node-ssh实现轻量级自动化部署

    [摘要] node脚本实现轻量级自动化部署 示例代码托管在:http://www.github.com/dashnowords/blogs 一. 需求描述 前端工程出包后实现简易的自动化部署. 二. ...

  6. 【nodejs原理源码赏析(6)】深度剖析cluster模块源码与node.js多进程

    示例代码托管在:http://www.github.com/dashnowords/blogs 博客园地址:<大史住在大前端>原创博文目录 华为云社区地址:[你要的前端打怪升级指南] 文章 ...

  7. 【nodejs原理源码赏析(4)】深度剖析cluster模块源码与node.js多线程(上)

    [摘要] 集群管理模块cluster浅析 示例代码托管在:http://www.github.com/dashnowords/blogs 一. 概述 cluster模块是node.js中用于实现和管理 ...

  8. 【nodejs原理源码赏析(7)】【译】Node.js中的事件循环,定时器和process.nextTick

    [摘要] 官网博文翻译,nodejs中的定时器 示例代码托管在:http://www.github.com/dashnowords/blogs 原文地址:https://nodejs.org/en/d ...

  9. 【nodejs原理源码赏析(3)】欣赏手术级的原型链加工艺术

    [摘要] 学习经典代码中的prototype加工 示例代码托管在:http://www.github.com/dashnowords/blogs 好的代码都差不多,烂的代码却各有各的烂法. 一. 概述 ...

最新文章

  1. 给网站管理员的建议:创建可利用的、可抓取的网站
  2. IOS开发之JSON序列化从客户端发送到服务器端
  3. ArcEngine开发体验(附许可)
  4. vim中的jk为什么是上下_JK轮胎的完整形式是什么?
  5. python中set()函数==》创建一个无序不重复的元素集(创将一个集合)
  6. *第6章 判别分析及R使用
  7. 【计算机网络】第一部分 概述(1) 数据通信和网络绪论
  8. 01-unity下载与安装
  9. python获取12306火车票_Python脚本实现12306火车票查询系统
  10. 为什么快手不能左右滑了_快手现在为什么不能滑动播放了
  11. 分布式Zookeeper-基础
  12. 计算机系统基础实验:二进制拆弹实验
  13. php fflush失败,php fflush 函数_PHP教程
  14. 扎拉赞恩 服务器 微信群,《魔兽世界怀旧服》杜隆塔尔扎拉赞恩攻略 任务怎么玩...
  15. ADDS:检查 AD Domain 的健康和复制状态
  16. Xamarin.Forms之AbsoluteLayout
  17. JavaFX+Jfoenix 学习笔记(五)--ContextMenu右键菜单
  18. SQL—分组数据(GOUP BY)
  19. 团建游戏---落难月球
  20. 信息学奥赛一本通:1163:阿克曼(Ackmann)函数

热门文章

  1. java.io.ioexception 拒绝访问,IOException异常 - 拒绝访问使用FileOutputStream中
  2. 打印异常堆栈_关于日志打印行号的性能案例
  3. python中plot函数的属性_Python matplotlib 学习-绘图函数
  4. zabbix利用mutt和msmtp配置邮件报警
  5. nodejs-express
  6. Java 工厂模式学习
  7. 如何恢复右键里新建记事本
  8. 关于日历的一个超级存储过程
  9. Windows10桌面美化推荐之Dock栏
  10. b超可以看出什么_B超可以查出什么