Node.js服务端框架Koa源码学习

目标

本文主要通过一个简单的例子来解释koa的内部原理。

koa的一个简单例子

<strong>图1是Koa的一个简单例子,下文会对这个例子的每行代码背后的逻辑做详细分析。

Node.js服务端框架Koa源码学习

图1 demo


koa内部文件组成


Node.js服务端框架Koa源码学习

图2 Koa代码文件


Node.js服务端框架Koa源码学习

图3 文件和具体类


  • application.js中包含了Application类和一些辅助方法
  • context.js主要作用是承载上下信息,并封装了处理上下文信息的操作
  • request.js中封装了处理请求信息的基本操作
  • response.js中封装了处理响应信息的基本操作

koa内部

在图1的例子中,执行const app = new koa()时,实际上构造了一个Application实例,<strong>图4为Application构造方法,构造方法中创建了Context、Request、Response等类的运行实例。关于Context、Response、Request类及方法介绍请参考

https://koajs.com/

下文约定request代指Request类实例,response代指Response类实例,context代指Context类实例。


Node.js服务端框架Koa源码学习

图4 Application构造方法


<strong>图1的例子中调用app.listen(3000)方法监听3000端口进来的http请求,listen方法内部创建了一个http.Server对象,并调用http.Server的listen方法。具体代码如<strong>图5。


Node.js服务端框架Koa源码学习

图5 listen犯法


<strong>图5中this.callback方法的源码如下<strong>图6中所示


Node.js服务端框架Koa源码学习

图6 callback


callback方法返回一个handleRequest函数,作为createServer的参数,当http.Server实例接收到一个http请求时,会将请求信息和请求响应对象传给handleRequest函数,具体指将http.IncomingMessage的实例req,和http.ServerResponse的实例res传给handleRequest函数。其中this.createContext函数的源码如下<strong>图7

http.IncomingMessage和http.ServerResponse信息可以参照node.js官网

Node.js服务端框架Koa源码学习

图7 createContext


<strong>图7中createContext的主要作用是将请求信息和响应信息封装在Request和Response类的运行实例中,并创建上下文类Context实例。context对象包含了Application、Request、Response等实例的引用。在this.callback方法中还有另一行很重要的代码,如下<strong>代码片段1。

代码片段1

<code>const fn = compose(this.middleware);/<code>

可以从<strong>图4中Application的构造方法中知道this.middleware是一个数组,该数组用来存储app.use方法传入的中间件函数。Application的use方法具体代码实现细节如<strong>图8,其中最关键的一行代码是this.middleware.push(fn)。


Node.js服务端框架Koa源码学习

图8 use


compose方法的代码实现包含在koa-compose包中,具体代码实现细节如<strong>图9


Node.js服务端框架Koa源码学习

图9 compose


compose方法接收this.middleware数组,返回一个匿名函数,该函数接收两个参数,上下文实例context和一个next函数,执行该匿名函数会执行this.middleware数组中的所有中间件函数,然后在执行传入的next函数。匿名函数调用是在Application的callback方法中,在<strong>图6

的callback方法的最后将执行上下文对象和compose方法返回的匿名函数作为参数传入this.handleRequest方法。接下来看一下this.handleRequest方法的具体细节,如<strong>图9。


Node.js服务端框架Koa源码学习

图9 handleRequest


在this.handleRequest方法中创建了错误处理方法onError和返回响应的方法

handleResponse。fnMiddleware就是compose方法返回的匿名函数。在this.handleRequest方法的最后执行匿名函数,并传入hanldeResponse和onError函数分别处理正常请求响应流程和异常情况。

<code>return fnMiddleware(ctx).then(handleResponse).catch(onerror);/<code>

执行fnMiddleware函数,实际上是执行之前传入所有中间件函数。在中间函数中可以拿到上下文对象的引用,通过上下文对象我们可以获取到经过封装的请求和响应实例,具体形式如<strong>图10。


Node.js服务端框架Koa源码学习

图10 中间间函数例子


在中间件方法中可以设置响应头信息、响应内容。以及读取数据库,获取html模版等。将需要返回给用户端的数据赋值给上下文对象context的body属性。respond方法的具体实现如<strong>图11。


Node.js服务端框架Koa源码学习

图11 respond


respond方法的主要作用是对返回的内容进行一些处理,然后调用node.js的http.ServerResponse实例的end方法,将具体内容返回给用户端。

request.js和response.js

ApplicationcreateContext方法中,将node.js的请求(http.IncomingMessage)和响应对象(http.ServerResponse)分别赋值给了Request类和Response类实例对象。Request中主要包含了处理请求的方法(实际上都是get方法,或者获取器),获取请求数据,例子如<strong>图12。


Node.js服务端框架Koa源码学习

图12 host方法例子


上面的代码中this.reqhttp.IncomingMessage实例,包含了http请求信息。Response中包含了处理请求响应的操作。例如设置响应状态信息,如<strong>图13


Node.js服务端框架Koa源码学习

图13 status


其中this.reshttp.ServerResponse对象实例。

到此处,图1中三行代码的背后逻辑已分析完成。


分享到:


相關文章: