route.js并不是exPRess里真正的路由代碼,他只是其中的一個組成部分,和router(router/index.js)是有區別的。下面先看一下重要的代碼。
function Route(path) { this.path = path; this.stack = []; // route handlers for various http methods this.methods = {};}Route.prototype.dispatch = function dispatch(req, res, done) {//done是router的next函數,執行后會跳到下一個中間件,從而跳過當前route的stack中剩下的函數 var idx = 0; var stack = this.stack; if (stack.length === 0) { return done();//done是開始執行該路由組件時傳進來的回調,執行完路由棧里的函數后執行done } var method = req.method.toLowerCase(); if (method === 'head' && !this.methods['head']) { method = 'get'; } req.route = this; next(); function next(err) { if (err && err === 'route') {//使用next('route')會不執行剩下的函數 return done(); } var layer = stack[idx++]; if (!layer) {//已經遍歷完layer了,跳到下一個router中的layer return done(err); } if (layer.method && layer.method !== method) {//方法不匹配,next return next(err); } if (err) {//通過層層篩選,最后可以執行的路由函數,先判斷有沒有錯誤,再執行相應的函數,每個layer都有對應的回調。 layer.handle_error(err, req, res, next); } else { layer.handle_request(req, res, next); } }};Route.prototype.all = function all() { var handles = flatten(slice.call(arguments)); for (var i = 0; i < handles.length; i++) { var handle = handles[i]; if (typeof handle !== 'function') { var type = toString.call(handle); var msg = 'Route.all() requires callback functions but got a ' + type; throw new TypeError(msg); } var layer = Layer('/', {}, handle); layer.method = undefined; this.methods._all = true; this.stack.push(layer); } return this;};首先route是作為一個layer對象的一個屬性,掛在在layer中的,route本身的結果類似于router,是一個數組,或者說是一個棧。元素的類型是layer。 1.構造函數比較簡單,主要是存儲路由的路徑和分配一個數組存儲layer數據結構。methods的存在主要是因為前端請求一個路徑,可以對應很多種http方法,比如get,post這種,所以methods變量主要是用在匹配路由時進行篩選時。 2.各種http方法和一個特殊的all方法的邏輯是類似的,主要是根據傳進來的0個或者多個回調函數,創建0個或者多個layer層,并且把他們加到route的數組中。 3.dispatch是最重要的函數,這個函數是在路由查找的過程中,匹配到了當前的路由時執行。核心的邏輯在next函數里,并且這個next函數和router里的next是不一樣的。代碼的第一行先判斷執行next的時候,是否傳入了route,是的話,就忽略當前棧中還沒有執行的函數,跳到下一個路由層。我們可以想象express的整個路由機制有點類似二維數組,比如是5*5的,我們先在一維數組里查找路由(router的邏輯),找到后,假設是第二行,然后我們執行第二行里的所有列對應的函數(route的邏輯)?;氐缴厦妫僭O是在第二列next到第三列時,執行next的時候傳入了route,那么第三列和后面的函數都不會被執行,路由機制會繼續從第三行往后找匹配的路徑。這里是通過執行done達到這個效果。
新聞熱點
疑難解答