漸進式Express原始碼學習6-獨孤求敗

sunkuo發表於2019-01-09

這是漸進式Express原始碼學習 | 小白也能懂原始碼系列文章的第六篇。

請結合該節程式碼閱讀Lesson6-獨孤求敗

目標特性和目標用法

這篇文章我們在第五篇文章的基礎上,實現一個稍微加強版的Express,功能包括

  • next可以向下傳遞錯誤物件
  • 錯誤捕捉

這篇文章要實現的express的期望用法如下


const express = require(`../index.js`)
const app = express()

app.get(`/foo`, function handle1 (req, res, next) {
  next(new Error(`Bang!`))
}, function handle2 (req, res, next) {
  res.end(`Will not go here`)
}, function handle3 (err, req, res, next) {
  console.log(`Error Caught! Error message is ${err.message}`)
  next(err)
})

app.get(`/foo`, function (req, res, next) {
  res.end(`Will not go here too`)
})

app.use(`/foo`, function (req, res, next) {
  res.end(`Will not go here too`)
})

app.get(`/foo`, function (err, req, res, next) {
  console.log(err.name)
  res.end(`Will not go here too`)
})

app.use(`/foo`, function (err, req, res, next) {
  console.log(`Error Caught! Error message is ${err.message}`)
  res.end(`Go here`)
})

app.listen(3000)
複製程式碼

在閱讀這篇文章之前,請務必瞭解express錯誤處理,例如上面的例子中,你需要知道丟擲的錯誤是在哪個環節捕捉的,否則閱讀這個文章會吃力

原始碼及講解

這一節,會引入兩個概念,路由中介軟體和非路由中介軟體
新的章節,主要有3個變化

  1. lib/route/layer.js
    1. 增加handle_error
  2. lib/route/route.js
    1. 修改.dispatch函式
      1. 如果有error,呼叫layer.handle_error
      2. 如果沒有error,呼叫layer.handle_request
  3. lib/route/index.js
    1. 增加use函式
    2. 調整handle函式

首先要講解,路由中介軟體和非路由中介軟體。路由中介軟體,通過app.verb新增,結構是處理函式掛載到layer上,layer推送到route上,route的dispatch函式又掛載到一個新的layer,這個layer再推送到Router的stack中。
結構類似這樣

漸進式Express原始碼學習6-獨孤求敗

而對於非路由中介軟體,直接掛載到layer上,然後推送到Router的stack
結構是這樣的

漸進式Express原始碼學習6-獨孤求敗

所以,二者結合後,結構是這樣的

漸進式Express原始碼學習6-獨孤求敗

理解了上面這些,我們看具體的程式碼
首先是lib/route/layer.js

漸進式Express原始碼學習6-獨孤求敗

他們的區別是如果你的layer的fn是function(req, res, next) ,呼叫這個layer的handle_error會直接掉過,只有當這個layer的fn是function(err, req, res, next)才會有效

再看lib/route/route.js

漸進式Express原始碼學習6-獨孤求敗

注意第44行到48行,route.dispatch函式會判斷是否有error,如果有,呼叫layer的handler_error函式,這樣正常的路由就會被跳過

再看lib/route/index.js

漸進式Express原始碼學習6-獨孤求敗

首先是增加了一個use函式,這個函式用來增加非路由中介軟體,直接建立一個layer,繫結函式後推送到stack

最後,看Router.handle,我們聚焦在next函式

漸進式Express原始碼學習6-獨孤求敗

看程式碼第55行,這個地方判斷是否是路由中介軟體,如果layer有route屬性,說明是路由中介軟體,否則不是。

漸進式Express原始碼學習6-獨孤求敗

在process_params裡也是,如果有錯誤,呼叫layer.handle_error,否則呼叫handle_request。

本文總結及預告

本文實現了一個加強的Express。到目前為止,一個基本的Express已經實現了。和真實的Express相比,只是一些細節差異

相關文章