Koa 解析

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

内容简介:本文将用一个饭店的例子帮助理解 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.IncomingMessage 和 http.ServerResponse ,也就是我们常见的 request 和 response 。

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

现在可以推测, callback 必定是返回一个函数,函数接收 request 和 response 两个参数。我们去看下 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 ,正好是一个函数,接收 req 和 res 两个参数。在这里我们终于又看到了 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 里我们发现又定义了两个新函数, onerror 和 handleResponse 。 handleResponse 作为 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 解析》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

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

Remote

Remote

Jason Fried、David Heinemeier Hansson / Crown Business / 2013-10-29 / CAD 26.95

The “work from home” phenomenon is thoroughly explored in this illuminating new book from bestselling 37signals founders Fried and Hansson, who point to the surging trend of employees working from hom......一起来看看 《Remote》 这本书的介绍吧!

在线进制转换器
在线进制转换器

各进制数互转换器

URL 编码/解码
URL 编码/解码

URL 编码/解码

SHA 加密
SHA 加密

SHA 加密工具