渐进式Express源码学习3-初露锋芒
发布于 7 个月前 作者 sunkuo 675 次浏览 来自 分享

这是渐进式Express源码学习 | 小白也能懂源码系列文章的第三篇。

请结合该节代码阅读Lesson3-初露锋芒

目录

  1. 渐进式Express源码学习1.万物归宗
  2. 渐进式Express源码学习2.道士下山
  3. 渐进式Express源码学习3.初露锋芒
  4. 渐进式Express源码学习4.如虎添翼
  5. 渐进式Express源码学习5.全副武装
  6. 渐进式Express源码学习6.独孤求败

目标特性和目标用法

这篇文章我们在第二篇文章的基础上,实现一个稍微加强版的Express,功能包括

  • 可以给一个方法添加多个中间件
  • 引入next参数

具体的用法如下

源码及讲解

先展示下目前的项目结构

和上篇文章不同的是,我们引入了route.js。目前源文件总共有三个,express.js, router/layer.js, router/route.js

这篇中,我们实现的大概思路是每一个layer对应一个中间件,用Route对象来保存layer。当请求到来时,调用Route的dispatch函数进行处理

上面的这个文字不理解没关系,看完代码就懂了,先看experss.js 和上篇文章相比,区别在两个函数,一个是init函数,一个是handle函数

对比下上篇文章

也就是说express.js里并没有接触Layer,而是初始化了一个Route,当请求到达是,调用route.dispatch进行处理。同样app.get等这些函数,也是调用Route对应的get函数。所以关键就是Route.js。先看下他的代码

在Route的构造函数里,Route保存了一个stack,保存了一个methods数组。当我们调用app.get(fn1, fn2)时,实际上调用的是route.get(fn1, fn2)。这部分实现在34-43行。对每一个handler,我们的做法是创建一个layer,然后push到route.stack中。

前方高能,重点是dispatch函数,这个地方要理解准确,实现很巧妙

当请求到来时,触发Route.dispatch函数,在dispatch函数中(20-32行),我们看看他是怎么做的。 首先他定义了一个计数器idx,定义了一个next函数。进入next之后,首先触发fn1, 传入的参数分别是req, res, next。注意最后这个next就是这个next函数。以我们自己的example做讲解

app.get(function (req, res, next) {
  req.user = {
    name: 'foo'
  }
  next()
})

上面代码中的next,其实就是dispatch的next函数。当我们在逻辑结尾调用next(), 其实也就是调用了dispatch中的next,从而idx 增加1 ,触发下一个layer的handle函数,直到我们不调用next(), 或者layer全部处理了

动手实验

我们首先通过命令node example/index.js运行样例 然后我们通过下面命令来测试我们的程序是否正常工作

curl -X GET http://localhost:3000

结果如图

按我们的预期工作

本文总结及预告

本文实现了一个加强的Express,他能让用户在一个路由添加多个中间件,同事引入了next参数。

回到顶部