express源码分析1:express实例的构造函数

gsbybbgsbybb -
express源码分析1:express实例的构造函数

这篇文章是express源码阅读系列文章的第一篇,这个系列的文章主要目的是想从一个Node.js的初学者的视角,结合express的API文档去分析解读express这个热门库的实现原理。

express的入口

从使用者的角度来看,express的入口应该是:

const express = require('express');

通过express仓库的package.json以及index.js可以看出,express整体的入口位于./lib/express。如下图

image.png

./lib/express主要包含以下几个部分:

express实例的构造函数:createApplicationexpress提供的实例对象:application、request、responseexpress提供的路由功能: Router,Routeexpress默认支持的middlewares: express.json()、express.query()等

这几个部分基本上可以和express的API文档对应起来

image.png

2、3、4部分主要就是简单的赋值导出,不做过多的分析express实例的构造函数

通常在使用express的时候会出现以下代码:

const express = require('express');
const app = express();

而前面提到的createApplication就是对应我们调用的express().

function createApplication() {
  var app = function(req, res, next) {
    app.handle(req, res, next);
  };

  mixin(app, EventEmitter.prototype, false);
  mixin(app, proto, false);

  // expose the prototype that will get set on requests
  app.request = Object.create(req, {
    app: { configurable: true, enumerable: true, writable: true, value: app }
  })

  // expose the prototype that will get set on responses
  app.response = Object.create(res, {
    app: { configurable: true, enumerable: true, writable: true, value: app }
  })

  app.init();
  return app;
}
express实例的类型

createApplication的返回值是一个function,而且是在express使用中很常见的listener

var app = function(req, res, next) {
    app.handle(req, res, next);
};

也就是说,创建的express实例本质上是一个listener,至于怎么使用,我们需要额外延伸一下Node.js中http模块提供的createServer方法。下面是一个简单的示例

const http = require('node:http');

// Create a local server to receive data from
const server = http.createServer((req, res) => {
  res.writeHead(200, { 'Content-Type': 'application/json' });
  res.end(JSON.stringify({
    data: 'Hello World!',
  }));
});

server.listen(8000);

结合上面的代码,可以发现express实例其实和Node API创建一个HttpServer所需要的listener参数很相似,为了不延伸太多额外的知识,我们先可以简单粗暴的理解为:express实例其实就是一个封装过的HttpServer对应的listener,这个listener会在创建HttpServer的时候被使用。

express实例上的方法挂载

createApplication中我们接下来会看到两个mixin相关的逻辑
mixin使用的是merge-descriptors这个库,所以这两行本质上都是在拓展express实例上的属性和方法。

mixin(app, EventEmitter.prototype, false);

通过合并EventEmitter的原型,让express实例上拥有了ononce等这些事件监听方法。

mixin(app, proto, false);

这一行则是给express实例上拓展更多的自定义方法,proto内容比较多,这边不做过多的延伸。

express实例上的request、response对象

在创建express实例的时候,会给实例增加requestresponse这两个属性,主要包含一下关键点

它们分别是以 express自己提供的requestresponse为原型 创建express自己提供的requestresponse为原型 分别是以Node。js的http模块中的http.IncomingMessage.prototypehttp.ServerResponse.prototype创建,并在上面拓展了一些自定义方法。实例上的requestresponse属性都额外增加了实例的引用,方便在处理请求和响应的时候,可以同时访问和修改express实例app.init()

这部分延伸的知识比较多,后面会放在express中application对象中去分析。

总结

这篇文章的重点主要分析了express实例的构造函数,函数本身内容比较少不过十多行代码,但是带出了一个重点知识:express实例是一个封装过的HttpServer对应的listener ,这个知识点将会在后面分析中经常出现。

特别申明:本文内容来源网络,版权归原作者所有,如有侵权请立即与我们联系(cy198701067573@163.com),我们将及时处理。

Tags 标签

node.jsexpress

扩展阅读

加个好友,技术交流

1628738909466805.jpg