【摘要】 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原理&源码赏析(5)】net模块与通讯的实现

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

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

    目录 一. net模块简介 二. Client-Server的通讯 2.1 server的建立 2.2 Socket的建立 三. IPC通讯 四. 撸一个简易的cluster通讯模型 示例代码托管在: ...

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

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

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

    目录 一. 概述 二. 线程与进程 三. cluster模块源码解析 3.1 起步 3.2 入口 3.3 主进程模块master.js 3.4 子进程模块child.js 四. 小结 示例代码托管在: ...

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

    目录 一. 概述 二. 原型链基础知识 三. Worker类的原型链加工 四. 实例的生成 五. 最后一个问题 六. 一些心得 示例代码托管在:http://www.github.com/dashno ...

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

    [摘要] cluster模块详解 示例代码托管在:http://www.github.com/dashnowords/blogs 阅读本章需要先阅读本系列前两章内容预热一下. 一. 引言 前两篇博文中 ...

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

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

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

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

  9. KOA中间件的基本运作原理

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

随机推荐

  1. NOIP模拟测试40

    考试时打了三个正解(或者叫能A的算法?),但是最终一个都没有A. 比较失败的一次考试. T1.队长快跑 先打了70分的dp,然后发现这个式子可以优化,拿线段树搞一下就好了,发现考试已经过去1h了,决定 ...

  2. .net里面<app.config>中value值不能填写特殊符号问题

    配置app.config或web.config的时候,经常要填写value值, 但是value值不能包含特殊字符,需要转义, 分享一下转义字符 App.config 实际上是 xml 文件,在标准 x ...

  3. nyoj 1071-不可以!(a*b + fabs(a*b))

    1071-不可以! 内存限制:64MB 时间限制:1000ms 特判: No 通过数:10 提交数:18 难度:1 题目描述: 判断:两个数x.y的正负性. 要求:不可以使用比较运算符,即" ...

  4. nyoj 108-士兵杀敌(一)(数学)

    108-士兵杀敌(一) 内存限制:64MB 时间限制:1000ms 特判: No 通过数:60 提交数:221 难度:3 题目描述: 南将军手下有N个士兵,分别编号1到N,这些士兵的杀敌数都是已知的. ...

  5. Netty创建服务器与客户端

    Netty 创建Server服务端 Netty创建全部都是实现自AbstractBootstrap.客户端的是Bootstrap,服务端的则是ServerBootstrap. 创建一个 HelloSe ...

  6. AV时间戳dts,pts。从ffmpeg解码过程看过来。

    解码过程中,dts由媒体流读入的包推动(解码包中的dts标记),dts在前进.pts是在dts前进到某处(截点)而进行动作的标记. 物理时间自然流逝,dts可以被控制同步与物理时间同一脚步节奏,也可以 ...

  7. python容器类型集合的操作

    集合(set):集合是一个无序的序列,集合中的元素可以是任意数据类型:表现形式是set(集合的元素),能够实现自动去重:集合传入的必须是一个hashable类型值,(不能存储字典格式的值):并且创建集 ...

  8. PostGIS 结合Openlayers以及Geoserver实现最短路径分析(二)

    前文讲述了怎么用ArcMap制作了测试数据,并导入了PostGIS,接下来我们需要结合PgRouting插件,对入库的数据再进行一下处理. 1.在pgAdmin中,执行下面的sql语句 --添加起点字 ...

  9. 2019-9-27:渗透测试,metasploit-framework初接触

    初次利用metasploit漏洞利用框架,入侵获取win7获取权限 目标机系统:windows7,无修复补丁 目标ip地址:192.168.20.131 任务:利用ms17-010,永恒之蓝漏洞,获取 ...

  10. css三大特效之层叠性

    css三大特效之层叠性