Express框架Router、Route和Layer对象如何使用

其他教程   发布日期:2023年11月11日   浏览次数:428

今天小编给大家分享一下Express框架Router、Route和Layer对象如何使用的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。

Layer

Layer 是什么? Express 中最小的存储单元,存储的重要内容包括 handle 也就是 fn、path 等路径。fn 就是中间件处理函数。重要的是 route 中能匹配:

  1. module.exports = Layer;
  2. function Layer(path, options, fn) {
  3. if (!(this instanceof Layer)) {
  4. return new Layer(path, options, fn);
  5. }
  6. var opts = options || {};
  7. this.handle = fn;
  8. this.name = fn.name || '<anonymous>';
  9. this.params = undefined;
  10. this.path = undefined;
  11. this.regexp = pathRegexp(path, this.keys = [], opts);
  12. this.regexp.fast_star = path === '*'
  13. this.regexp.fast_slash = path === '/' && opts.end === false
  14. }
  15. Layer.prototype.handle_error = function handle_error(error, req, res, next) {}
  16. Layer.prototype.handle_request = function handle(req, res, next) {}
  17. Layer.prototype.match = function match(path) {} // 返回 boolean

看看哪些的内容实例化了 Layer 的构造函数。Layer 的最主要的作用就是,被路由匹配到,然后取出 handle 函数最后调用,消费 handle 函数。

  • Route

一个 Route 的栈 stack 中,可以存放多个 Layer。

  1. Route.prototype.all = function all() {
  2. /**/
  3. var layer = Layer('/', {}, handle);
  4. /**/
  5. }
  6. Route.prototype[method] = function(){
  7. /**/
  8. var layer = Layer('/', {}, handle);
  9. /**/
  10. }
  • Router 中

  1. proto.route = function route(path) {
  2. // ***
  3. var layer = new Layer(path, {
  4. sensitive: this.caseSensitive,
  5. strict: this.strict,
  6. end: true
  7. }, route.dispatch.bind(route));
  8. // ***
  9. this.stack.push(layer);
  10. };
  1. proto.use = function use(fn) {
  2. var layer = new Layer(path, {
  3. sensitive: this.caseSensitive,
  4. strict: false,
  5. end: false
  6. }, fn);
  7. this.stack.push(layer);
  8. }

在 Router 中的 route 和 use 函数,使用 Layer 构造函数实例化 layer, 然后将 layer 压到 stack 中保存卡里,方便以后匹配。

  • layer 的匹配方法

  1. function matchLayer(layer, path) {
  2. try {
  3. return layer.match(path);
  4. } catch (err) {
  5. return err;
  6. }
  7. }

从上面的代码中知道,layer 对象的 match 方法,根据路径进行匹配, match 返回 boolean. 在匹配的时候主要处理了两个属性:

  1. this.params = undefined;
  2. this.path = undefined;

接下来看 matchLayer 函数, matchLayer 调用在 Router.handle 函数的 next 函数中。

Route

  1. module.exports = Route;
  2. function Route(path) {
  3. this.path = path;
  4. this.stack = [];
  5. this.methods = {};
  6. }
  7. Route.prototype._handles_method = function _handles_method(method) {/*...*/}
  8. Route.prototype._options = function _options() {/*...*/}
  9. Route.prototype.dispatch = function dispatch(req, res, done) {/*...*/}
  10. Route.prototype.all = function all() {/*...*/}
  11. // 扩展 methods 包中的方法

Router

Router 就是 proto

  1. var proto = module.exports = function(options) {/*...*/}
  2. proto.param = function param(name, fn) {/*...*/}
  3. proto.handle = function handle(req, res, out) {/*...*/}
  4. proto.process_params = function process_params(layer, called, req, res, done) {/*...*/}
  5. proto.use = function use(fn) {/*...*/}
  6. proto.route = function route(path) {/*...*/}
  7. // 扩展 methods + all 上所有的方法

注意: Router.handle 函数.

  1. var stack = self.stack;
  2. while (match !== true && idx < stack.length) {/*...*/}

在 while 循环中,使用 idx 中取出 layer 和 path然后交给 matchLayer 函数, 得到匹配结果。如果调用的内容正常:

  1. layer.handle_request(req, res, next) // 最终会得到中间件的处理函数

接下来盘点, Router/Route/Layer 的常用方法

方法统计

  • Router

Router 方法 说明
Router param 参数
Router handle 处理函数
Router process_params 处理参数
Router use 中间件
Router route 路由
Router [methods]/all 各种方法
  • Route

Route 方法 说明
Route _handles_method 私有处理函数
Route _options 私有选项
Route dispatch 派发请求和响应
Route all 各种方法
Route [methods] 各种方法
  • Layer

Layer 方法 说明
Layer handle_error 处理错误
Layer handle_request 处理请求
Layer match 根据路径匹配路由并返回 boolean

看 Router 和 Route 有相同的方法: all/[methods]。使用 Router.route 的方法通过 path 方法关联。同时 咋 Router.route 中实例化 Layer ,然后将 layer 保存在 Router 的 stack 中。

两个 stack

从上面的分析中,知道了 Router 中有 stack,Route 中也有 stack, 在 stack 中添加内容(也就是 Layer)一般都是与路由和中间件相关。

  • Router 的 use 方法中,包含了实例化 Layer, 并存储在 Router 级别的 stack 中。

  • Router 的 route 中,实例化了 Layer, 并存储在 Router 级别的 stack 中。

  • Router 的 [methods]/all 方法中,调用了 route 方法,自然也存储了 stack

取出 stack 中 layer

取出 Layer 发生在 Route 的 dispatch 函数 的 next 函数中,此时需要调用 layer 中匹配到的参数。

从 Router 到 layer 的路径

  • Router 是被 express 单独的输出出去的。

  • Router 实例化之后,可以调用 use/[methods] 实例化 Layer 并保存 stack 中,当然也可调用 Router.route 方法。

Router.route 方法中的 dispatch

  1. var layer = new Layer(path, {
  2. sensitive: this.caseSensitive,
  3. strict: this.strict,
  4. end: true
  5. }, route.dispatch.bind(route));

route.dispatch 在此处 bind 绑定,此时作为 Layer 构造函数的第三个参数,保存为 handle, 最后会被拿出调用。此时就进入了 next 函数调用阶段。

next 函数

next 函数是 Express 中间件的基础,dispatch 函数从 当前的 stack 中拿出 layer 的实际情况调用 layer 不同的方法。

  1. if (layer.method && layer.method !== method) {
  2. next(err)
  3. }

当 layer 中的方法或者等于但当前的方法时,调用自己,此时 next 函数发生了递归。否则进入 handle 相关方法处理请求和处理错阶段,此时 next 方法发生了递归调用。

以上就是Express框架Router、Route和Layer对象如何使用的详细内容,更多关于Express框架Router、Route和Layer对象如何使用的资料请关注九品源码其它相关文章!