express源码分析
关于本次对
express
源码的学习,我想带着 几个问题来阅读源码:
序号 | 问题描述 |
---|---|
1 | express所导出的模块中都有哪些元素 |
2 | express中的methods(get/post/put/delete等)、set、use、all方法是如何实现的 |
3 | express针对req、res追加的属性都有哪些 |
4 | express中的渲染引擎是如何实现的 |
5 | 从express的实现中可以学到什么 |
在回答上述的问题时,先看 的一个模块结构图:
与connect
类似,express
也是一个中间件函数(关于中间件的知识,可以看下之前关于中间件实现原理文档)中所描述的,
同样从一函数开始,通过返回的带req
、res
、next
等参数的方式,来提供给到相关的http
模块作为回调,使得每一个请求动作都经过这个express
框架!唯一不同的是,这个创建出来的app继承了EventEmitter
,使得我们可以通过on/emit
的方式来设置对应的监听以及触发监听!!
另外的,根据这个中间件,在创建成功的app中,默认都提供了query
、expressInit
两个中间件,用于做一些初始化工作以及参数的解析动作!
一、express中所导出的模块都有哪些元素
1、Router
每一次客户端请求时创建的一个路由对象(这里是所有的请求都共享的Router对象),用以缓存处理客户端请求的路由执行路径对象堆栈
Layer
,它底层也是一中间件实现类,用来自动从stack
列表中获取每一个中间件对象。
2、Route
用来精准匹配路径的一个路由器对象,一般与
Layer
关联,Route与Router的关系就有点类似于vue-router中的Route与Router
两者的关系,前者代表精准匹配客户端请求路径,后者用户缓存客户端执行时所有中间件的执行顺序
3、Layer
用来代表每一个被加入进来的中间件对象,其缓存的
handle
属性则指向用户设置的中间件回调函数!!
4、那么这三个模块之间是如何配合工作的?
要想理解这三个模块之间是如何协同的,先看一下 的一个关于其使用方式
- 常规的最普遍的使用方式 将回调缓存在
_router
中的stack
中的Layer
中的Route
中的stack
中的Layer
中的handle
属性中;- 使用了两个连续的中间件处理的方式 将两个回调缓存在
_router
中的stack
中的Layer
中的Route
中的stack
中的两个Layer
中的对应handle
属性中;- 使用了use的方式 将两个回调缓存在
_router
中的stack
中的Layer
中的对应handle
属性- 使用了route精准匹配的方式 将回调缓存在
_router
中的stack
中的Layer
中的Route
中的stack
中的Layer
中的handle
属性中;- 采用Router模块化使用的方式 将两个回调缓存在
_router
中的stack
中的Layer
中的对应handle
属性,且拥有以名字为router
的Layer- 采用混用的方式
将上述的情况进行一个总结就是:使用use(包括Router)
的方式,将会将所有的中间件按照定义顺序依次作为一Layer
存储在app._router.stack
中,而其他的中间件则存储在app._router.stack.route.stack
中
这么些不同的关于路由的使用方式,对应的匹配规则,那么这三者之间她们是如何协同工作的呢:
首先先看一下关于express的一个运行日志输出,如上图所示,也就是在设置自定义的中间件的时候,express已经帮助我们设置好了这个express的基础中间件了, 相应的,这边也同时整理了关于这个设置对应中间件的一个过程,如 图所示:
二、express中的methods(get/post/put/delete等)、set、use、all的实现过程
通过对引用的
http-methods
所提供的所有方法进行一个迭代器,并对每一个方法统一进行追加对应的函数方法,使得app可以直接调用对应的method方法,而其中的调用顺序路径如下:
三、express针对req、res所追加的属性都有哪些?
- req.route,发生于Router中间件的handle处理过程,用来精准匹配对应的path,并捆绑相应的fn中间件回调函数到Layer中的handle属性中;
- req.params,发生于Router中间件的handle处理过程,用来捕获客户请求所传递的参数数据;
- req.query,发生于express所提供的公共的query中间件的过程中,根据请求类型来获取对应的查询参数;
- res的一系列响应动作,详见之前的文章
四、express中的渲染引擎是如何实现的?
首先,先来看一下关于模版引擎的使用与实现: 为什么使用
res.render()
方法,就可以实现一个html页面的渲染结果呢? 概括成一句话,就是:根据预先存留的关于如何标志唯一渲染引擎的标示,然后在响应的时候,通过引擎的render
函数,将结果渲染成为一个html字符串,通过res.render函数来渲染出去,而所提供的视图渲染引擎,一般都提供了对应的express的一个兼容处理动作!
五、从express的实现中可以学到什么?
- 通过在导入的
http-method
方法数据枚举中,采用[]
的方式来为对象添加属性,实现动态化添加所有的http请求方法的回调处理动作; - 中间件允许嵌套中间件的方式,可以是在某个具体的中间件中采用中间件的技巧,使得在某个中间件内部可以通过预先定义好的中间件顺序来执行对应的逻辑动作!