koa不愧为小而美,主要代码很少。简单来说,
1,koa封装了node的http.createServer((req,res)=>{})的入参req,res到ctx同名属性(一个自定义对象)中,
并且额外提供了ctx.request,ctx.request提供一些快捷的操作。
const app = new Koa()
app.use(middlewareFn)
2.方法use函数接收参数fn,放入中间件middleware[]数组里面。
  use(fn) {
this.middleware.push(fn);
return this;
}

通过用户调用listen(port)调用this.handleRequest函数:

  listen(...args) {
const server = http.createServer(this.callback());
return server.listen(...args);
}
callback() {
const fn = compose(this.middleware);
const handleRequest = (req, res) => {
const ctx = this.createContext(req, res);
return this.handleRequest(ctx, fn);
}; return handleRequest;
}
调用处理过的middleware函数:
  handleRequest(ctx, fnMiddleware) {
const res = ctx.res;
const handleResponse = () => respond(ctx);
return fnMiddleware(ctx).then(handleResponse).catch(onerror);
}
即处理过的middleware数组:
function compose (middleware) {
return function (context, next) {
// last called middleware #
let index = -1
return dispatch(0)
function dispatch (i) {
if (i <= index) return Promise.reject(new Error('next() called multiple times'))
index = i
let fn = middleware[i]
if (i === middleware.length) fn = next
if (!fn) return Promise.resolve()
try {
return Promise.resolve(fn(context, dispatch.bind(null, i + 1)));
} catch (err) {
return Promise.reject(err)
}
}
}
}

递归的展开就是洋葱模型了:

const [fn1, fn2, fn3] = this.middleware;
const fnMiddleware = function(ctx){
return Promise.resolve(
fn1(context, function next(){
return Promise.resolve(
fn2(context, function next(){
return Promise.resolve(
fn3(context, function next(){
return Promise.resolve();
})
)
})
)
})
);
};
fnMiddleware(ctx).then(handleResponse).catch(onerror);

ctx:

createContext(req, res) {
const context = Object.create(this.context);
const request = context.request = Object.create(this.request);
const response = context.response = Object.create(this.response);
context.app = request.app = response.app = this;
context.req = request.req = response.req = req;
context.res = request.res = response.res = res;
request.ctx = response.ctx = context;
request.response = response;
response.request = request;
context.originalUrl = request.originalUrl = req.url;
context.state = {};
return context;
}

koa源代码解析的更多相关文章

  1. Spring源代码解析

    Spring源代码解析(一):IOC容器:http://www.iteye.com/topic/86339 Spring源代码解析(二):IoC容器在Web容器中的启动:http://www.itey ...

  2. Arrays.sort源代码解析

    Java Arrays.sort源代码解析 Java Arrays中提供了对所有类型的排序.其中主要分为Primitive(8种基本类型)和Object两大类. 基本类型:采用调优的快速排序: 对象类 ...

  3. Spring源代码解析(收藏)

    Spring源代码解析(收藏)   Spring源代码解析(一):IOC容器:http://www.iteye.com/topic/86339 Spring源代码解析(二):IoC容器在Web容器中的 ...

  4. volley源代码解析(七)--终于目的之Response&lt;T&gt;

    在上篇文章中,我们终于通过网络,获取到了HttpResponse对象 HttpResponse是android包里面的一个类.然后为了更高的扩展性,我们在BasicNetwork类里面看到.Volle ...

  5. Cocos2d-x源代码解析(1)——地图模块(3)

    接上一章<Cocos2d-x源代码解析(1)--地图模块(2)> 通过前面两章的分析,我们能够知道cocos将tmx的信息结构化到 CCTMXMapInfo.CCTMXTilesetInf ...

  6. Android EventBus源代码解析 带你深入理解EventBus

    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/40920453,本文出自:[张鸿洋的博客] 上一篇带大家初步了解了EventBus ...

  7. 源代码解析Android中View的layout布局过程

    Android中的Veiw从内存中到呈如今UI界面上须要依次经历三个阶段:量算 -> 布局 -> 画图,关于View的量算.布局.画图的整体机制可參见博文 < Android中Vie ...

  8. Android xUtils3源代码解析之网络模块

    本文已授权微信公众号<非著名程序猿>原创首发,转载请务必注明出处. xUtils3源代码解析系列 一. Android xUtils3源代码解析之网络模块 二. Android xUtil ...

  9. Android View体系(八)从源代码解析View的layout和draw流程

    相关文章 Android View体系(一)视图坐标系 Android View体系(二)实现View滑动的六种方法 Android View体系(三)属性动画 Android View体系(四)从源 ...

  10. 《nginx源代码解析》系列分享专栏

    <nginx源代码解析>系列分享专栏 解析nginx源代码,从main函数开始,一步步解读nginx运行原理,同时进行nginx第三方模块的开发,努力做到知其然,知其所以然 <ngi ...

随机推荐

  1. hash和hash tree

    在理想情况下,我们希望不经过任何比较,一次存取便能得到所查的记录,那就必须在记的存储位置和它的关键字之间建立一个确定的对应关系,使每个关键字和一个唯一的存储位置对应,因而在查找时候,根据这个对应关系与 ...

  2. springmvc 能进入Controller,但是前端页面还是404

    问题现象: 1.Controller里面的方法上已经加了注解 @ResponseBody 2.能进入controller的方法里面: 3.前端返回状态码 404: 4.控制台没有异常信息: 问题原因: ...

  3. Day13 字符串的常用方法

    API帮助文档的使用流程 在索引的位置搜索自己要查看的类 看包 目的:是不是 Java.lang包(核心包),不需要编写导包代码(import) -------不是 java.lang包,都需要编写导 ...

  4. 51nod 1594 Gcd and Phi

    Link 题解: $ans = \sum_{i = 1}^{n}\sum_{j = 1}^{n}phi(gcd(phi(i), phi(j)))$ $=\sum_{d = 1}^{n}phi(d)\s ...

  5. 对象可能是类数组对象 不具备数组的原型内的方法 所以可以用call或者apply把this指向改成数组或对象原型

    const arr = [] 2Object.prototype.toString.call(arr) === '[object Array]' // true 3 4 const obj = {} ...

  6. 使用a标签锚点实现顺滑效果

    scroll-behavior:smooth;//使用该方法使用a标签锚点的时候会实现平滑 xxx.scrollIntoView({ behavior: "smooth" })

  7. 创建一个与a.txt文件同目录下的另一个文件b.txt

    File file1 = new("d:\\a\\a.txt"); File file2 = new(file1.getParent(),"b.txt"): F ...

  8. css节流

    众所周知,函数节流(throttle)是 JS 中一个非常常见的优化手段,可以有效避免函数过于频繁的执行. 举个例子:一个保存按钮,为了避免重复提交或者服务器考虑,往往需要对点击行为做一定的限制,比如 ...

  9. SpringBoot 块形式的配置文件写法(简单示例)

    1.配置文件写法 spring: profiles: dev quartz: auto-startup: true --- spring: profiles: local quartz: auto-s ...

  10. elementUI合并单元格

    <el-table :data="tableDataFormat" border :header-cell-style="{background:'#FAFAFA' ...