成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

教你從寫(xiě)一個(gè)迷你koa-router到閱讀koa-router源碼

yzzz / 1376人閱讀

摘要:本打算教一步步實(shí)現(xiàn),因?yàn)橐忉尩奶嗔?,所以先?jiǎn)化成版本,從實(shí)現(xiàn)部分功能到閱讀源碼,希望能讓你好理解一些。

本打算教一步步實(shí)現(xiàn)koa-router,因?yàn)橐忉尩奶嗔?,所以先?jiǎn)化成mini版本,從實(shí)現(xiàn)部分功能到閱讀源碼,希望能讓你好理解一些。
希望你之前有讀過(guò)koa源碼,沒(méi)有的話,給你鏈接

最核心需求-路由匹配

router最重要的就是路由匹配,我們就從最核心的入手

router.get("/string",async (ctx, next) => {
  ctx.body = "koa2 string"
})

router.get("/json",async (ctx, next) => {
  ctx.body = "koa2 json"
})

我們希望

路徑訪問(wèn) /string 頁(yè)面顯示 "koa2 string"

路徑訪問(wèn) /json 頁(yè)面顯示 "koa2 json"

先分析
收集開(kāi)發(fā)者輸入的信息配置

1.我們需要一個(gè)數(shù)組,數(shù)組里每個(gè)都是一個(gè)對(duì)象,每個(gè)對(duì)象包含路徑,方法,函數(shù),傳參等信息
這個(gè)數(shù)組我們起個(gè)名字叫stack

const stack = []

2.對(duì)于每一個(gè)對(duì)象,我們起名叫l(wèi)ayer
我們把它定義成一個(gè)函數(shù)

function Layer() {
    
}

我們把頁(yè)面比喻成一個(gè)箱子,箱子是對(duì)外的,箱子需要有入口,需要容納。把每一個(gè)router比作放在箱子里的物件,物件是內(nèi)部的

定義兩個(gè)js頁(yè)面,router.js做為入口,對(duì)于當(dāng)前頁(yè)面的訪問(wèn)的處理,layer.js包含開(kāi)發(fā)者已經(jīng)約定好的規(guī)則

router.js

module.exports = Router;

function Router(opts) {
  // 容納layer層
  this.stack = [];
};

layer.js

module.exports = Layer;

function Layer() {

};

我們?cè)赗outer要放上許多方法,我們可以在Router內(nèi)部掛載方法,也可以在原型上掛載函數(shù)

但是要考慮多可能Router要被多次實(shí)例化,這樣里面都要開(kāi)辟一份新的空間,掛載在原型就是同一份空間。
最終決定掛載在原型上

方法有很多,我們先實(shí)現(xiàn)約定幾個(gè)常用的吧

const methods = [
  "get",
  "post",
  "put",
  "head",
  "delete",
  "options",
];
methods.forEach(function(method) {
  Router.prototype[method] = function(path,middleware){
    // 對(duì)于path,middleware,我們需要把它交給layer,拿到layer返回的結(jié)果
    // 這里交給另一個(gè)函數(shù)來(lái)是實(shí)現(xiàn),我們叫它register就是暫存的意思
    this.register(path, [method], middleware);
    // 因?yàn)間et還可以繼續(xù)get,我們返回this
    return this
  };
});
實(shí)現(xiàn)layer的溝通
Router.prototype.register = function (path, methods, middleware) {
  let stack = this.stack;
  let route = new Layer(path, methods, middleware);
  stack.push(route);
  
  return route
};

這里我們先去寫(xiě)layer

const pathToRegExp = require("path-to-regexp");

function Layer(path, methods, middleware) {
  // 把方法名稱放到methods數(shù)組里
  this.methods = [];
  // stack盛放中間件函數(shù)
  this.stack = Array.isArray(middleware) ? middleware : [middleware];
  // 路徑
  this.path = path;
  // 對(duì)于這個(gè)路徑生成匹配規(guī)則,這里借助第三方
  this.regexp = pathToRegExp(path);
  // methods
  methods.forEach(function(method) {
    this.methods.push(method.toUpperCase());
    // 綁定layer的this,不然匿名函數(shù)的this指向window
  }, this);

};
// 給一個(gè)原型方法match匹配返回true
Layer.prototype.match = function (path) {
  return this.regexp.test(path);
};

回到router層

定義match方法,根據(jù)Developer傳入的path, method返回 一個(gè)對(duì)象(包括是否匹配,匹配成功layer,和匹配成功的方法)

Router.prototype.match = function (path, method) {
  const layers = this.stack;
  let layer;
  const matched = {
    path: [],
    pathAndMethod: [],
    route: false
  };
   //循環(huán)寄存好的stack層的每一個(gè)layer
  for (var len = layers.length, i = 0; i < len; i++) {
    layer = layers[i];

    //layer是提前存好的路徑, path是過(guò)來(lái)的path
    if (layer.match(path)) {
      // layer放入path,為什么不把path傳入,一是path已經(jīng)沒(méi)用了,匹配了就夠了,layer含有更多信息需要用
      matched.path.push(layer);
      //如果methods什么也沒(méi)寫(xiě),或者如果方法里含有你的過(guò)來(lái)的方法,那么把layer放入pathAndMethod
      if (layer.methods.length === 0 || ~layer.methods.indexOf(method)) {
        matched.pathAndMethod.push(layer);
        // 路徑匹配,并且有方法
        if (layer.methods.length) matched.route = true;
      }
    }
  }

  return matched;
};

給Developer一個(gè)方法

app.use(index.routes())

這里不考慮傳多個(gè)id,和多次匹配情況,拿到匹配的函數(shù)

Router.prototype.routes = function(){
  var router = this;

  const dispatch = function dispatch(ctx, next) {
    const path = ctx.path
    const method = ctx.method
    const matched = router.match(path, ctx.method);

    if (!matched.route) return next();
    const matchedLayers = matched.pathAndMethod
    // 先不考慮多matchedLayers多stack情況
    return matchedLayers[0].stack[0](ctx, next);
  }

  return dispatch
}

此時(shí)一個(gè)迷你koa-router已經(jīng)實(shí)現(xiàn)了

讀源碼 需求實(shí)現(xiàn) 實(shí)現(xiàn)匹配

方法名匹配,路徑匹配,還要滿足動(dòng)態(tài)參數(shù)的傳遞

并且還要給很懶的開(kāi)發(fā)者一個(gè)router.all()
也就是說(shuō)不用區(qū)分方法了

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/102805.html

相關(guān)文章

  • Koa-router 優(yōu)先級(jí)問(wèn)題

    摘要:?jiǎn)栴}描述在使用作為路由遇到了一個(gè)優(yōu)先級(jí)問(wèn)題如下代碼在訪問(wèn)時(shí)路由會(huì)優(yōu)先匹配到路由返回這個(gè)問(wèn)題就很尷尬了項(xiàng)目空閑下來(lái)去翻看源碼終于找到了原因問(wèn)題原因的源碼并不長(zhǎng)和兩個(gè)文件加起來(lái)共一千多行代碼建議可以結(jié)合這篇文章閱讀其中造成這個(gè)問(wèn)題的原因 問(wèn)題描述 在使用Koa-router作為路由遇到了一個(gè)優(yōu)先級(jí)問(wèn)題.如下代碼 // routerPage.js file const router = re...

    Paul_King 評(píng)論0 收藏0
  • koa源碼閱讀[2]-koa-router

    摘要:第三篇,有關(guān)生態(tài)中比較重要的一個(gè)中間件第一篇源碼閱讀第二篇源碼閱讀與是什么首先,因?yàn)槭且粋€(gè)管理中間件的平臺(tái),而注冊(cè)一個(gè)中間件使用來(lái)執(zhí)行。這里寫(xiě)入的多個(gè)中間件都是針對(duì)該生效的。 第三篇,有關(guān)koa生態(tài)中比較重要的一個(gè)中間件:koa-router 第一篇:koa源碼閱讀-0 第二篇:koa源碼閱讀-1-koa與koa-compose koa-router是什么 首先,因?yàn)閗oa是一個(gè)管...

    oneasp 評(píng)論0 收藏0
  • koa-router 源碼淺析

    摘要:代碼結(jié)構(gòu)執(zhí)行流程上面兩張圖主要將的整體代碼結(jié)構(gòu)和大概的執(zhí)行流程畫(huà)了出來(lái),畫(huà)的不夠具體。那下面主要講中的幾處的關(guān)鍵代碼解讀一下。全局的路由參數(shù)處理的中間件組成的對(duì)象。 代碼結(jié)構(gòu) showImg(https://segmentfault.com/img/remote/1460000007468236?w=1425&h=1772); 執(zhí)行流程 showImg(https://segmentf...

    SillyMonkey 評(píng)論0 收藏0
  • 玩轉(zhuǎn)Koa -- koa-router原理解析

    摘要:四路由注冊(cè)構(gòu)造函數(shù)首先看了解一下構(gòu)造函數(shù)限制必須采用關(guān)鍵字服務(wù)器支持的請(qǐng)求方法,后續(xù)方法會(huì)用到保存前置處理函數(shù)存儲(chǔ)在構(gòu)造函數(shù)中初始化的和屬性最為重要,前者用來(lái)保存前置處理函數(shù),后者用來(lái)保存實(shí)例化的對(duì)象。 一、前言 ??Koa為了保持自身的簡(jiǎn)潔,并沒(méi)有捆綁中間件。但是在實(shí)際的開(kāi)發(fā)中,我們需要和形形色色的中間件打交道,本文將要分析的是經(jīng)常用到的路由中間件 -- koa-router。 ??...

    wthee 評(píng)論0 收藏0
  • iKcamp團(tuán)隊(duì)制作|基于Koa2搭建Node.js實(shí)戰(zhàn)(含視頻)? 路由koa-router

    路由koa-router——MVC 中重要的環(huán)節(jié):Url 處理器 ?? iKcamp 制作團(tuán)隊(duì) 原創(chuàng)作者:大哼、阿干、三三、小虎、胖子、小哈、DDU、可木、晃晃 文案校對(duì):李益、大力萌、Au、DDU、小溪里、小哈 風(fēng)采主播:可木、阿干、Au、DDU、小哈 視頻剪輯:小溪里 主站運(yùn)營(yíng):給力xi、xty 教程主編:張利濤 視頻地址:https://www.cctalk.com/v/151...

    netmou 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<