一、前言
Koa為了保持自身的簡潔,并沒有捆綁中間件。但是在實際的開發中,我們需要和形形色色的中間件打交道,本文將要分析的是經常用到的路由中間件 -- koa-router。
如果你對Koa的原理還不了解的話,可以先查看Koa原理解析。
二、koa-router概述
koa-router的源碼只有兩個文件:router.js和layer.js,分別對應Router對象和Layer對象。
Layer對象是對單個路由的管理,其中包含的信息有路由路徑(path)、路由請求方法(method)和路由執行函數(middleware),并且提供路由的驗證以及params參數解析的方法。
相比較Layer對象,Router對象則是對所有注冊路由的統一處理,并且它的API是面向開發者的。
接下來從以下幾個方面全面解析koa-router的實現原理:
Layer對象的實現 路由注冊 路由匹配 路由執行流程三、Layer
Layer對象主要是對單個路由的管理,是整個koa-router中最小的處理單元,后續模塊的處理都離不開Layer中的方法,這正是首先介紹Layer的重要原因。
function Layer(path, methods, middleware, opts) { this.opts = opts || {}; // 支持路由別名 this.name = this.opts.name || null; this.methods = []; this.paramNames = []; // 將路由執行函數保存在stack中,支持輸入多個處理函數 this.stack = Array.isArray(middleware) ? middleware : [middleware]; methods.forEach(function(method) { var l = this.methods.push(method.toUpperCase()); // HEAD請求頭部信息與GET一致,這里就一起處理了。 if (this.methods[l-1] === 'GET') { this.methods.unshift('HEAD'); } }, this); // 確保類型正確 this.stack.forEach(function(fn) { var type = (typeof fn); if (type !== 'function') { throw new Error( methods.toString() + " `" + (this.opts.name || path) +"`: `middleware` " + "must be a function, not `" + type + "`" ); } }, this); this.path = path; // 1、根據路由路徑生成路由正則表達式 // 2、將params參數信息保存在paramNames數組中 this.regexp = pathToRegExp(path, this.paramNames, this.opts);};Layer構造函數主要用來初始化路由路徑、路由請求方法數組、路由處理函數數組、路由正則表達式以及params參數信息數組,其中主要采用path-to-regexp方法根據路徑字符串生成正則表達式,通過該正則表達式,可以實現路由的匹配以及params參數的捕獲:
// 驗證路由Layer.prototype.match = function (path) { return this.regexp.test(path);}// 捕獲params參數Layer.prototype.captures = function (path) { // 后續會提到 對于路由級別中間件 無需捕獲params if (this.opts.ignoreCaptures) return []; return path.match(this.regexp).slice(1);}根據paramNames中的參數信息以及captrues方法,可以獲取到當前路由params參數的鍵值對:
新聞熱點
疑難解答
圖片精選