這是漸進式Express源碼學習 | 小白也能懂源碼系列文章的第六篇。javascript
請結合該節代碼閱讀Lesson6-獨孤求敗java
這篇文章咱們在第五篇文章的基礎上,實現一個稍微增強版的Express,功能包括git
這篇文章要實現的express的指望用法以下github
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錯誤處理,例如上面的例子中,你須要知道拋出的錯誤是在哪一個環節捕捉的,不然閱讀這個文章會吃力express
這一節,會引入兩個概念,路由中間件和非路由中間件 新的章節,主要有3個變化app
首先要講解,路由中間件和非路由中間件。路由中間件,經過app.verb添加,結構是處理函數掛載到layer上,layer推送到route上,route的dispatch函數又掛載到一個新的layer,這個layer再推送到Router的stack中。 結構相似這樣函數
而對於非路由中間件,直接掛載到layer上,而後推送到Router的stack 結構是這樣的學習
因此,兩者結合後,結構是這樣的ui
理解了上面這些,咱們看具體的代碼 首先是lib/route/layer.jsspa
他們的區別是若是你的layer的fn是function(req, res, next) ,調用這個layer的handle_error會直接掉過,只有當這個layer的fn是function(err, req, res, next)纔會有效
再看lib/route/route.js
注意第44行到48行,route.dispatch函數會判斷是否有error,若是有,調用layer的handler_error函數,這樣正常的路由就會被跳過
再看lib/route/index.js
首先是增長了一個use函數,這個函數用來增長非路由中間件,直接建立一個layer,綁定函數後推送到stack
最後,看Router.handle,咱們聚焦在next函數
看代碼第55行,這個地方判斷是不是路由中間件,若是layer有route屬性,說明是路由中間件,不然不是。
在process_params裏也是,若是有錯誤,調用layer.handle_error,不然調用handle_request。
本文實現了一個增強的Express。到目前爲止,一個基本的Express已經實現了。和真實的Express相比,只是一些細節差別