内容简介:本文将用一个饭店的例子帮助理解 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 解析》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- 每秒解析千兆字节的 JSON 解析器开源,秒杀一大波解析器!
- 注册中心 Eureka 源码解析 —— EndPoint 与 解析器
- 新一代Json解析库Moshi源码解析
- mybatis源码配置文件解析之三:解析typeAliases标签
- MySQL内核源码解读-SQL解析之解析器浅析
- Laravel 核心——IoC 服务容器源码解析(服务器解析)
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
加密与解密(第4版)
段钢 / 电子工业出版社 / 2018-10-1 / 198
《加密与解密(第4版)》以加密与解密为切入点,讲述了软件安全领域的基础知识和技能,如调试技能、逆向分析、加密保护、外壳开发、虚拟机设计等。这些知识彼此联系,读者在掌握这些内容之后,很容易就能在漏洞分析、安全编程、病毒分析、软件保护等领域进行扩展。从就业的角度来说,掌握加密与解密的相关技术,可以提高自身的竞争能力;从个人成长的角度来说,研究软件安全技术有助于掌握一些系统底层知识,是提升职业技能的重要......一起来看看 《加密与解密(第4版)》 这本书的介绍吧!