Koa 解析

栏目: Node.js · 发布时间: 5年前

内容简介:本文将用一个饭店的例子帮助理解 Koa 做了哪些事情。先看下 Koa 给的官方 Demo:我们运行这几行代码,就可以在浏览器打开

本文将用一个饭店的例子帮助理解 Koa 做了哪些事情。

先看下 Koa 给的官方 Demo:

const Koa = require('koa');
const app = new Koa();

// response
app.use(ctx => {
  ctx.body = 'Hello Koa';
});

app.listen(3000);
复制代码

我们运行这几行代码,就可以在浏览器打开 localhost:3000 ,页面会出现 Hello Koa 的文字。现在我们就来分析一下这段代码都做了哪些事情。

为了方便理解,我们把抽象的东西实体化,假设服务是一个饭店,饭店里有服务员,厨师等员工,有各种菜品,然后等待顾客上门消费,随后会套用这个例子来理解。

首先分析一下前两行代码

const Koa = require('koa');
const app = new Koa();
复制代码

这两行代码只是简单的引入 Koa,然后 new 一个实例,那么这个 new Koa() 都做了哪些事情呢?

通过 package.json 可以看出 Koa 的入口文件是 lib/application.js ,在这个文件中我们可以看到,该文件导出的其实是 Application 这个类,那么紧接着看下这个类的构造函数 constructor

constructor() {
    super();
    this.proxy = false;
    this.middleware = [];
    this.subdomainOffset = 2;
    this.env = process.env.NODE_ENV || 'development';
    this.context = Object.create(context);
    this.request = Object.create(request);
    this.response = Object.create(response);
    if (util.inspect.custom) {
      this[util.inspect.custom] = this.inspect;
    }
}
复制代码

只是简单的做了些初始化。没什么好说的,接着往下看。

app.use(ctx => {
  ctx.body = 'Hello Koa';
});
复制代码

Application 中找到 use 方法的定义

use(fn) {
  // ...
  this.middleware.push(fn);
  return this;
}
复制代码

use 接收了一个函数作为参数,并把函数 push 进了 middleware ,而我们在 constructor 里得知 middleware 就是一个数组。那么只能接着往下看。

到了最后一行代码

app.listen(3000);
复制代码

application 中我们可以找到 listen 的定义

listen(...args) {
    debug('listen');
    const server = http.createServer(this.callback());
    return server.listen(...args);
  }
复制代码

这个方法的定义也很简单,是用 node 的 http 模块启动了一个 server,关键在传给 http.createServer 的参数,这个参数是个方法,在查看方法 callback 的定义之前,我们先看下 http.createServer

createServer 返回一个 server ,接收一个函数,这个函数会在有请求的时候执行,函数会接收 http.IncomingMessagehttp.ServerResponse ,也就是我们常见的 requestresponse

server.listen 方法就开始监听,一旦有请求映射到 3000 端口,就会执行传入到 createServer 的函数。

现在可以推测, callback 必定是返回一个函数,函数接收 requestresponse 两个参数。我们去看下 callback 的定义。

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;
}
复制代码

callback 返回 handleRequest ,正好是一个函数,接收 reqres 两个参数。在这里我们终于又看到了 middleware ,之前使用 use 将一个函数 push 进去后,就不知道做了什么了。这里发现是把它传进了 handleRequest 里( compose 是把一组函数封装成 Promise ,一次调用,这里先不详解),那么先跳过 createContext ,直接看 handleRequest

handleRequest(ctx, fnMiddleware) {
    const res = ctx.res;
    res.statusCode = 404;
    const onerror = err => ctx.onerror(err);
    const handleResponse = () => respond(ctx);
    onFinished(res, onerror);
    return fnMiddleware(ctx).then(handleResponse).catch(onerror);
  }
复制代码

handleRequest 里我们发现又定义了两个新函数, onerrorhandleResponsehandleResponse 作为 fnMiddleware 到回调,也就是运行完所有的 middleware 后会执行 handleResponse 。看 respond 的定义。

function respond(ctx) {
  // ...
  const res = ctx.res;
  let body = ctx.body;
  // ...
  res.end(body);
}
复制代码

respond 里看到了 res.end(body) ,这也说明请求倍返回了,也就是我们在浏览器看到的 Hello Koa。

那么我们套用之前饭店的例子梳理一下, new Koa 就表示我们的饭店成立了,而 app.use 就表述我们新增了员工(其实职位更贴切,但是员工更方便理解,就假设每个职位就一个人),而 middleware 就是我们的员工列表。 app.listen 表示我们在门口挂上了“营业中”的牌子,等待顾客光临。当有顾客进来时,员工就要工作了,让顾客就坐,点餐,厨师做饭,然后上餐… 这就是所有 middleware 开始一次执行。最后顾客吃完离开,也就是 respond 。还有 onerror ,相当于保安和经理,用来处理意外情况,比如顾客菜里吃出了蟑螂,顾客钱不够,就需要保安出来锤一顿。

参照我们饭店的例子,现在我们在从头梳理一下,我们 new 了一个 Koa 对象,然后像 middleware 里添加了一个函数,最后开始 listen 。当有人请求我们所 listen 的端口时,我们就会把所有的 middleware 执行一遍,最后执行 respond ,(这里我们忽略的 context 和其他内容),将结果返回给那个请求的人。


以上所述就是小编给大家介绍的《Koa 解析》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

加密与解密(第4版)

加密与解密(第4版)

段钢 / 电子工业出版社 / 2018-10-1 / 198

《加密与解密(第4版)》以加密与解密为切入点,讲述了软件安全领域的基础知识和技能,如调试技能、逆向分析、加密保护、外壳开发、虚拟机设计等。这些知识彼此联系,读者在掌握这些内容之后,很容易就能在漏洞分析、安全编程、病毒分析、软件保护等领域进行扩展。从就业的角度来说,掌握加密与解密的相关技术,可以提高自身的竞争能力;从个人成长的角度来说,研究软件安全技术有助于掌握一些系统底层知识,是提升职业技能的重要......一起来看看 《加密与解密(第4版)》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具