内容简介:先复习一下使用原生 Node.js 搭建一个 Web 服务器。可以看到,我们只需要关注相同的逻辑对应到 Koa 上来,代码量差不多。
先复习一下使用原生 Node.js 搭建一个 Web 服务器。
var http = require('http'); var server = http.createServer(function (req, res) { res.writeHead(200, {'Content-Type': 'text/plain'}) res.end('Hello world\n') }) server.listen(3000) 复制代码
可以看到,我们只需要关注 http.createServer()
传入的回调函数和 server.listen()
传入的参数即可。一般来讲, server.listen()
传入 Web 服务器监听的端口号,而 http.createServer()
传入的回调函数则负责处理 HTTP 请求并给出响应。
相同的逻辑对应到 Koa 上来,代码量差不多。
const koa = require('koa'); const app = new koa(); app.use(ctx => { ctx.body = 'Hello world' }) app.listen(3000) 复制代码
仔细观察我们发现, server.listen
对应于 app.listen
,而 http.createServer()
传入的回调函数在 Koa 里则是利用 app.use()
传入的。实际上,处理请求和响应的操作就是由 app.use()
传入的函数完成的。
基于这个思路,我们可以开始分析 Koa 源码中涉及到上面描述的部分。
源码文件
Koa 的源码只有四个文件。其中,负责对外暴露方法的是 application.js
, context.js
封装了请求和响应作为上下文 ctx
,而 request.js
(请求)和 response.js
(响应)则为 context.js
提供支持。
核心文件是 application.js
,主要是两个方法:
1. app.listen() - 监听端口
封装并不复杂,仅仅是将原生 Node.js 启动 Web 服务器的操作放在了一个函数里。
listen(...args) { const server = http.createServer(this.callback()); return server.listen(...args); } 复制代码
看到这里大概也能猜出来,我们的逻辑(处理请求和响应)都在 this.callback()
里面。这也是后面要讲的重头戏。
2. app.use() - 添加中间件
除去校验参数合法性外,真正实现功能的只有一句:
use(fn) { // ... this.middleware.push(fn); // ... } 复制代码
实际上就是将传入的中间件函数添加到 this.middleware
中。最终,就是这些中间件函数,构成了处理请求和响应的绝大多数逻辑。
谁来处理中间件
文件开始的时候,我们已经得到一个思路, http.createServer()
传入的回调函数负责处理每个 HTTP 请求并给出响应,而现在我们发现传入的是 this.callback()
的返回值,我们来看看它的代码。
callback() { const fn = compose(this.middleware); // ... const handleRequest = (req, res) => { const ctx = this.createContext(req, res); return this.handleRequest(ctx, fn); }; return handleRequest; } 复制代码
返回的 handleRequest
局部变量就是我们一直提到的那个回调函数,它与原生 Node.js 搭建的服务器一样,接收请求(req)和响应(res)两个参数。每次请求到来时,这个函数都会被调用,它完成两个工作:
-
创建一个上下文
ctx
,封装了本次的请求和响应 -
将上下文
ctx
和函数fn
交由this.handleRequest()
处理
对了,这个函数的第一行我们没有介绍,它用到了 app.use()
传进来的中间件 this.middleware
。
const fn = compose(this.middleware); 复制代码
中间件机制是 Koa 设计中非常巧妙的一部分,利用中间件我们可以为 Web 服务器提供各种各样的功能。鉴于篇幅,我们只介绍如何把传入的多个中间件变成我们想要的回调函数。
这里用到的是 koa-compose
这个 NPM 包,它把传入的多个中间件 "捏" 成一个回调函数 fn
,由它对上下文 ctx
进行处理,当然也就是 HTTP 请求和响应。
处理请求和响应
上节提到,上下文 ctx
和函数 fn
交给了 this.handleRequest()
处理,它进行了以下几项工作:
-
在
ctx
中将响应默认置为404 -
定义错误处理函数
onerror
,具体会由ctx.onerror()
执行 -
定义响应处理函数
handleResponse
,具体会由this.respond()
执行 -
调用中间件 “捏” 成的单个回调函数
fn
处理上下文ctx
,其返回一个 Promise 对象,在其then中发出响应(调用handleResponse
),若出错则处理错误(调用onerror
)
总结
总的来说,可以将由 Koa 搭建的 Web 服务器的工作原理分为两个过程:
1. 启动服务器
利用 this.callback()
将中间件 “捏” 成一个回调函数传给 http.createServer
,同时实例化了一个 Server
对象,调用其 listen
方法启动服务器。
2. 处理请求并响应
this.callback()
返回的是一个回调函数,每个新的请求到来, Server
就会调用它并传入请求和响应两个参数。它会创建包含 req 和 res 的上下文 ctx
,并调用回调函数 fn
处理 ctx
,继而发出响应或错误。而 fn
是由我们调用 app.use()
传入的中间件 “捏” 成的。也就是说,中间件处于核心位置,根据我们想要的逻辑处理请求和响应。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- Kafka 源码分析(一):源码环境搭建
- Zeppelin 源码分析(一):源码环境搭建
- Elasticsearch 源码解析:环境搭建
- Kafka 探险:源码环境搭建
- vue源码debug环境搭建
- Spring源码解析之环境搭建
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
极简算法史:从数学到机器的故事
[法] 吕克•德•布拉班迪尔 / 任轶 / 人民邮电出版社 / 2019-1 / 39.00元
数学、逻辑学、计算机科学三大领域实属一家,彼此成就,彼此影响。从古希腊哲学到“无所不能”的计算机,数字、计算、推理这些貌似简单的概念在三千年里融汇、碰撞。如何将逻辑赋予数学意义?如何从简单运算走向复杂智慧?这背后充满了人类智慧的闪光:从柏拉图、莱布尼茨、罗素、香农到图灵都试图从数学公式中证明推理的合理性,缔造完美的思维体系。他们是凭天赋制胜,还是鲁莽地大胆一搏?本书描绘了一场人类探索数学、算法与逻......一起来看看 《极简算法史:从数学到机器的故事》 这本书的介绍吧!