1. // 用法
  2. var express = require("express")
  3. var app = express()
  4. app.use((req, res, next) => {
  5. next()
  6. })
  7. app.get("/", function(req, res) {
  8. res.send("Hello world!")
  9. })
  10. app.listen(3000)
  11. //************************************************ */
  12. // 中间件实现原理
  13. function use(route, fn) {
  14. var handle = fn
  15. var path = route
  16. // 不传入route则默认为'/',这种基本是框架处理参数的一种套路
  17. if (typeof route !== "string") {
  18. handle = route
  19. path = "/"
  20. }
  21. // 存储中间件,与koa不同,这里会存储路由与函数的映射关系
  22. this.stack.push({ route: path, handle: handle })
  23. // 以便链式调用
  24. return this
  25. }
  26. // 函数自身内部维护自增标识符,next函数,调用next函数,消费队列,把next函数传递给
  27. function handle(req, res, out) {
  28. let index = 0
  29. function next(err) {
  30. // 依次取出中间件
  31. const { router, handle } = stack[index++]
  32. // 终止条件
  33. if (!stack[index++]) {
  34. defer(done, err)
  35. return
  36. }
  37. // 路由匹配规则,如果不匹配,跳过当前中间件执行
  38. if (router !== path) {
  39. return next(err)
  40. }
  41. // 执行中间件,传递错误,与上下文对象,next函数
  42. call(layer.handle, route, err, req, res, next)
  43. }
  44. next()
  45. }
  46. function call(handle, route, err, req, res, next) {
  47. if (err && handle.length === 4) {
  48. // 错误处理中间件
  49. handle(err, req, res, next)
  50. return
  51. } else if (!err) {
  52. // 请求处理中间件
  53. handle(req, res, next)
  54. return
  55. }
  56. }

connect 中间件与 koa 中间件差异

  • connect中提供路由匹配的功能,Koa中间件的执行并不需要匹配路由,所以注册的中间件每一次请求都会执行
  • connect在捕获中间件的异常时,通过next携带error一个个中间件验证,直到错误处理中间件,而Koa中则是用Promise包装中间件,一旦中间件发生异常,那么会直接触发reject状态,直接在Promise的catch中处理就行
  • Koa中通过继承event,暴露error事件让开发者自定义异常处理
  • Koa中res.end由中间件执行完成之后自动调用,这样避免在connect忘记调用res.end导致用户得不到任何反馈
  • Koa中采用了async/await语法让开发者利用同步的方式编写异步代码