首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Koa 源码研读

Koa 源码研读

作者头像
李振
发布2021-11-26 11:30:45
发布2021-11-26 11:30:45
41000
代码可运行
举报
文章被收录于专栏:乱码李乱码李
运行总次数:0
代码可运行

简介

Koa 是一个非常轻量的 web 开发框架,由 Express 团队打造。相较于 Express,Koa 使用 async 函数解决异步的问题,并且完全脱离中间件,非常优雅,而且 Koa 代码简洁友好,很适合初学者阅读。

Koa 代码结构

可以看到 Koa 的结构非常简单,lib 文件夹下面放着 koa 的核心文件:

application.js

application 是 koa 的入口文件,export 出一个 Application 的类(继承自 events.Emitter)。application 有以下几个主要(public)的 api:

  • listen: 实现对 http.createServer() 的封装,传入的参数 callback 中完成中间件合并,错误监听以及上下文的创建和 request 的处理。
  • use: 我们通常使用 app.use(function) 将中间件添加到应用程序。use 方法中,koa 将中间件(函数)添加到 this.middleware 数组中。
  • callback: koa-compose 将中间件组合在一起, 然后返回一个 request 回调函数,同时给 listen 作为回调。
  • toJSON: 返回一个去除私有属性(_开头)的对象。
代码语言:javascript
代码运行次数:0
运行
复制
module.exports = class Application extends Emitter {
  listen(...args) {
    debug('listen');
    const server = http.createServer(this.callback());
    return server.listen(...args);
  }
  
  use(fn) {
    if (typeof fn !== 'function') throw new TypeError('middleware must be a function!');
    this.middleware.push(fn);
    return this;
  }
  
  callback() {
    const fn = compose(this.middleware);
    
    if (!this.listenerCount('error')) this.on('error', this.onerror);
    
    const handleRequest = (req, res) => {
      const ctx = this.createContext(req, res);
      return this.handleRequest(ctx, fn);
    };
  
    return handleRequest;
  }
}

context.js

context 是我们在使用 koa 中最常接触到的 ctx,就是一个暴露出来的对象。context 中实现了对 cookie 的 get set 操作,这也是我们可以直接使用 ctx 对 cookie 操作的原理。除此之外,ctx 中最重要的是 delegate,也就是委托。我们简单看一下代码:

代码语言:javascript
代码运行次数:0
运行
复制
delegate(proto, 'response')
  .method('attachment')
  .method('redirect')
  .method('remove')
  .method('vary')
  .method('set')
  .method('append')
  .method('flushHeaders')
  .access('status')
  .access('message')
  .access('body')
  .access('length')
  .access('type')
  .access('lastModified')
  .access('etag')
  .getter('headerSent')
  .getter('writable');

以上的 proto 就是 ctx,实现了对 response 对象的代理,比如我们可以通过使用 ctx.status 来访问 ctx.response.status。

同样的,request 上面的属性和方法也被代理到了 ctx 中:

代码语言:javascript
代码运行次数:0
运行
复制

delegate(proto, 'request')
  .method('acceptsLanguages')
  .method('acceptsEncodings')
  .method('acceptsCharsets')
  .method('accepts')
  .method('get')
  .method('is')
  .access('querystring')
  .access('idempotent')
  .access('socket')
  .access('search')
  .access('method')
  .access('query')
  .access('path')
  .access('url')
  .access('accept')
  .getter('origin')
  .getter('href')
  .getter('subdomains')
  .getter('protocol')
  .getter('host')
  .getter('hostname')
  .getter('URL')
  .getter('header')
  .getter('headers')
  .getter('secure')
  .getter('stale')
  .getter('fresh')
  .getter('ips')
  .getter('ip');

ctx.hostname 即是 ctx.request.hostname。

request.js && response.js

request.js 和 response.js 中完成对 Koa Request/Response 对象的封装,可以通过 request.xxx/response.xxx 对其进行操作。其中使用了很多 get 和 set 方法。

实现一个简单的 moa

  • 首先需要完成对 http 模块的封装,可以使用创建服务器。
  • 然后完成 request 和 response 对象的封装,以及将其代理到 context 对象上。
  • 然后需要处理中间件以及实现洋葱模型。
  • 最后需要完成对错误的处理和异常捕获。
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018-12-05,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 简介
    • Koa 代码结构
    • application.js
    • context.js
    • request.js && response.js
  • 实现一个简单的 moa
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档