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;
}

最新文章

  1. Java 多线程编程
  2. GJM :SqlServer语言学习笔记
  3. excel导出
  4. 计算机网络(6)-----运输层概述和UDP协议
  5. 【BZOJ1812】riv(多叉树转二叉树,树形DP)
  6. SQL Server 2014里的IO资源调控器
  7. 用 Java 实现断点续传 (HTTP)
  8. pycharm最新注册方法 pycharm最新激活方法 2016pycharm最新注册方法
  9. java三线程循环有序打印ABC
  10. 关于微软企业库中依赖注入容器Unity两种生成对象的实现u
  11. thinkphp3.2.2前后台公用类架构问题
  12. 构建一个基于 Spring 的 RESTful Web Service
  13. 10. 混淆矩阵、总体分类精度、Kappa系数
  14. codeforces432D Prefixes and Suffixes(kmp+dp)
  15. iOS视图控制器之间delegate传值教程
  16. 采用WindowManager添加您自己的自定义视图
  17. DOM操作中,遍历动态集合的注意事项。ex: elem.children
  18. 故障定位之查找附近点GeoHash研讨
  19. nodemailer + express + h5 拖拽文件上传 实现发送邮件
  20. hive on tez配置

热门文章

  1. 【C#异步】异步多线程的本质,上下文流转和同步
  2. h5项目自适应字体和宽高。用rem
  3. unity通过隐藏layer隐藏组件
  4. rust vec排序
  5. MS-TCT: Multi-Scale Temporal ConvTransformer for Action Detection概述
  6. 学习操作系统P4 理解并发程序执行 (Peterson算法、模型检验与软件自动化工具)
  7. Servlet(服务连接器)
  8. 面向对象程序设计第三次blog
  9. PHP中的超级变量
  10. antd切换主题