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. c++_成员函数回调

    //--------------------------------------------------------------------------- #include <vcl.h> ...

  2. 退役*CPCer的找实习总结

    从2月底开始到今天,我终于拿到了第一个也是唯一一个offer(字节跳动).找实习的过程告一段落,所以想记录一下这段时间的经历. 最开始找$meopass$学长内推了小马智行,很快就接到了面试通知(再次 ...

  3. Vue npm run test 错误 (node:16672) UnhandledPromiseRejectionWarning: CssSyntaxError:xxxx.Unknown word

    记一次运行代码上传的测试服务器遇到的坑,昨天上传还好好的,今天上传就报以下错误,以为是忘记下什么插件了,简单粗暴的把node_modules下载重装了,结果还是不行,看看什么情况吧~~~ npm ru ...

  4. 创建一个spring项目

  5. Software_programming_EnterpriseArch_ServiceWithSingleTonFactory

    19:50:31 <UML 模式和应用> P322 系统需要支持多种第三方外部服务,例如费用计算,授权服务,库存系统,都具有不同的API, 而且还无法改变. 解决方案之一: 使用 单例模式 ...

  6. uniapp - 设置代理

    uniapp - 设置代理 HbuilderX 找到 manifest.json 文件,点击源码视图 "h5" : { "title" : "案件要素 ...

  7. leecode64. 最小路径和(动态规划)

    64. 最小路径和 给定一个包含非负整数的 m x n 网格 grid ,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小. 说明:每次只能向下或者向右移动一步. 示例 1: 输入:gri ...

  8. 网络爬虫Python(一)

    1.爬取页面,打印页面信息 1 import requests 2 3 # get请求 4 response_get=requests.get("https://www.baidu.com& ...

  9. npm install报错C:\Users\Guyang\AppData\Roaming\npm-cache\_logs\xxx-14T01_06_33_159Z-debug-0.log

    先看报错 可以看到报错提示,给了个日志路径 有的兄弟看到其他博客给了一个命令 npm cache clean --force 或者 npm config set strict-ssl false 说是 ...

  10. [Err] [Dtf] 1044 - Access denied for user 'root'@'localhost' to database 'information_schema'

    在从Oracle向mysql数据库传输数据时,报出来这个错误,原因是因为没有打开mysql数据库,在navicat里打开mysql,并选中要传输的数据库 再重复传输一下即可