成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

不到300行代碼構(gòu)建精簡的koa和koa-router(mini-koa)

tuomao / 3063人閱讀

摘要:詳細(xì)代碼如下追蹤賦值里面的是子路由設(shè)計子路由設(shè)計這個比較簡單,每個子路由維護(hù)一個路由監(jiān)聽列表,然后通過調(diào)用的函數(shù)添加到主路由列表上。

前言

鑒于之前使用expresskoa的經(jīng)驗(yàn),這兩天想嘗試構(gòu)建出一個koa精簡版,利用最少的代碼實(shí)現(xiàn)koa和koa-router,同時也梳理一下Node.js網(wǎng)絡(luò)框架開發(fā)的核心內(nèi)容。

實(shí)現(xiàn)后的核心代碼不超過300行,源代碼配有詳細(xì)的注釋。

核心設(shè)計 API調(diào)用

mini-koa的API設(shè)計中,參考koa和koa-routerAPI調(diào)用方式。

Node.js的網(wǎng)絡(luò)框架封裝其實(shí)并不復(fù)雜,其核心點(diǎn)在于http/httpscreateServer方法上,這個方法是http請求的入口。

首先,我們先回顧一下用Node.js來啟動一個簡單服務(wù)。

// https://github.com/qzcmask/mini-koa/blob/master/examples/simple.js
const http = require("http")
const app = http.createServer((request, response) => {
  response.end("hello Node.js")
})
app.listen(3333, () => {
  console.log("App is listening at port 3333...")
})
路由原理

既然我們知道Node.js的請求入口在createServer方法上,那么我們可以在這個方法中找出請求的地址,然后根據(jù)地址映射出監(jiān)聽函數(shù)(通過get/post等方法添加的路由函數(shù))即可。

其中,路由列表的格式設(shè)計如下:

// binding的格式
{
"/": [fn1, fn2, ...],
"/user": [fn, ...],
...
}
// fn/fn1/fn2的格式
{
  method: "get/post/use/all",
  fn: "路由處理函數(shù)"
}
難點(diǎn)分析 next()方法設(shè)計

我們知道在koa中是可以添加多個url監(jiān)聽函數(shù)的,其中決定是否傳遞到下一個監(jiān)聽函數(shù)的關(guān)鍵在于是否調(diào)用了next()函數(shù)。如果調(diào)用了next()函數(shù)則先把路由權(quán)轉(zhuǎn)移到下一個監(jiān)聽函數(shù)中,處理完畢再返回當(dāng)前路由函數(shù)。

mini-koa中,我把next()方法設(shè)計成了一個返回Promise fullfilled的函數(shù)(這里簡單設(shè)計,不考慮next()傳參的情況),用戶如果調(diào)用了該函數(shù),那么就可以根據(jù)它的值來決定是否轉(zhuǎn)移路由函數(shù)處理權(quán)。

判斷是否轉(zhuǎn)移路由函數(shù)處理權(quán)的代碼如下:

let isNext = false
const next = () => {
  isNext = true
  return Promise.resolve()
}
await router.fn(ctx, next)
if (isNext) {
  continue
} else {
  // 沒有調(diào)用next,直接中止請求處理函數(shù)
  return
}
use()方法設(shè)計

mini-koa提供use方法,可供擴(kuò)展日志記錄/session/cookie處理等功能。

use方法執(zhí)行的原理是根據(jù)請求地址在執(zhí)行特定路由函數(shù)之前先執(zhí)行mini-koa調(diào)用use監(jiān)聽的函數(shù)

所以這里的關(guān)鍵點(diǎn)在于怎么找出use監(jiān)聽的函數(shù)列表,假設(shè)現(xiàn)有監(jiān)聽情況如下:

app.use("/", fn1)
app.use("/user", fn2)

如果訪問的url/user/add,那么fn1和fn2都必須要依次執(zhí)行。

我采取的做法是先根據(jù)/字符來分割請求url,然后循環(huán)拼接,查看路由綁定列表(binding)中有沒有要use的函數(shù),如果發(fā)現(xiàn)有,添加進(jìn)要use的函數(shù)列表中,沒有則繼續(xù)下一次循環(huán)。

詳細(xì)代碼如下:

// 默認(rèn)use函數(shù)前綴
let prefix = "/"
// 要預(yù)先調(diào)用的use函數(shù)列表
let useFnList = []

// 分割url,使用use函數(shù)
// 比如item為/user/a/b映射成[("user", "a", "b")]
const filterUrl = url.split("/").filter(item => item !== "")
// 該reduce的作用是找出本請求要use的函數(shù)列表
filterUrl.reduce((cal, item) => {
  prefix = cal
  if (this.binding[prefix] && this.binding[prefix].length) {
    const filters = this.binding[prefix].filter(router => {
      return router.method === "use"
    })
    useFnList.push(...filters)
  }
  return (
    "/" +
    [cal, item]
      .join("/")
      .split("/")
      .filter(item => item !== "")
      .join("/")
  )
}, prefix)
ctx.body響應(yīng)

通過ctx.body = "響應(yīng)內(nèi)容"的方式可以響應(yīng)http請求。它的實(shí)現(xiàn)原理是利用了ES6Object.defineProperty函數(shù),通過設(shè)置它的setter/getter函數(shù)來達(dá)到數(shù)據(jù)追蹤的目的。

詳細(xì)代碼如下:

// 追蹤ctx.body賦值
Object.defineProperty(ctx, "body", {
  set(val) {
    // set()里面的this是ctx
    response.end(val)
  },
  get() {
    throw new Error(`ctx.body can"t read, only support assign value.`)
  }
})
子路由mini-koa-router設(shè)計

子路由mini-koa-router設(shè)計這個比較簡單,每個子路由維護(hù)一個路由監(jiān)聽列表,然后通過調(diào)用mini-koaaddRoutes函數(shù)添加到主路由列表上。

mini-koaaddRoutes實(shí)現(xiàn)如下:

addRoutes(router) {
  if (!this.binding[router.prefix]) {
    this.binding[router.prefix] = []
  }
  // 路由拷貝
  Object.keys(router.binding).forEach(url => {
    if (!this.binding[url]) {
      this.binding[url] = []
    }
    this.binding[url].push(...router.binding[url])
  })
}
用法

使用示例如下,源代碼可以在github上找到:

// examples/server.js
// const { Koa, KoaRouter } = require("mini-koa")
const { Koa, KoaRouter } = require("../index")
const app = new Koa()
// 路由用法
const userRouter = new KoaRouter({
  prefix: "/user"
})

// 中間件函數(shù)
app.use(async (ctx, next) => {
  console.log(`請求url, 請求method: `, ctx.req.url, ctx.req.method)
  await next()
})

// 方法示例
app.get("/get", async ctx => {
  ctx.body = "hello ,app get"
})

app.post("/post", async ctx => {
  ctx.body = "hello ,app post"
})

app.all("/all", async ctx => {
  ctx.body = "hello ,/all 支持所有方法"
})

// 子路由使用示例
userRouter.post("/login", async ctx => {
  ctx.body = "user login success"
})

userRouter.get("/logout", async ctx => {
  ctx.body = "user logout success"
})

userRouter.get("/:id", async ctx => {
  ctx.body = "用戶id: " + ctx.params.id
})

// 添加路由
app.addRoutes(userRouter)

// 監(jiān)聽端口
app.listen(3000, () => {
  console.log("> App is listening at port 3000...")
})
總結(jié)

挺久沒有造輪子了,這次突發(fā)奇想造了個精簡版的koa,雖然跟常用的koa框架有很大差別,但是也實(shí)現(xiàn)了最基本的API調(diào)用和原理。

造輪子是一件難能可貴的事,程序員在學(xué)習(xí)過程中不應(yīng)該崇尚拿來主義,學(xué)習(xí)到一定程度后,要秉持能造就造的態(tài)度,去嘗試?yán)斫夂屯诰蜉喿颖澈蟮脑砗退枷搿?/p>

當(dāng)然,通常來說,自己造的輪子本身不具備多大的實(shí)用性,沒有經(jīng)歷過社區(qū)大量的測試和實(shí)際應(yīng)用場景的打磨,但是能加深自己的理解和提高自己的能力也是一件值得堅(jiān)持的事。

人生是一段不斷攀登的高峰,只有堅(jiān)持向前,才能看到新奇的東西。

最后附上項(xiàng)目的Github地址,歡迎Star或Fork支持,謝謝。

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

轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/103631.html

相關(guān)文章

  • 從零搭建Koa2 Server

    摘要:于是翻遍與各大網(wǎng)站,都沒找到一個好用的輕一點(diǎn)的腳手架,也找不到一個清晰些的搭建介紹?,F(xiàn)在把搭建過程介紹下,看能不能方便下入門的同學(xué)。創(chuàng)建一個文件夾,命名。記得先裝好以上版本一路回車,根據(jù)提示輸入信息。但這只是初步的搭建了下。 前幾天想寫個小爬蟲程序,準(zhǔn)備后端就用koa2。于是翻遍github與各大網(wǎng)站,都沒找到一個好用的、輕一點(diǎn)的koa2腳手架,也找不到一個清晰些的搭建介紹。githu...

    JellyBool 評論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、可木、晃晃 文案校對:李益、大力萌、Au、DDU、小溪里、小哈 風(fēng)采主播:可木、阿干、Au、DDU、小哈 視頻剪輯:小溪里 主站運(yùn)營:給力xi、xty 教程主編:張利濤 視頻地址:https://www.cctalk.com/v/151...

    netmou 評論0 收藏0
  • Koa v2.x 中文文檔 Koa 對比 Express

    摘要:使用承諾和異步功能來擺脫回調(diào)地獄的應(yīng)用程序,并簡化錯誤處理。它暴露了自己的和對象,而不是的和對象。因此,可被視為的模塊的抽象,其中是的應(yīng)用程序框架。這使得中間件對于整個堆棧而言不僅僅是最終應(yīng)用程序代碼,而且更易于書寫,并更不容易出錯。 Koa 與 Express 此系列文章的應(yīng)用示例已發(fā)布于 GitHub: koa-docs-Zh-CN. 可以 Fork 幫助改進(jìn)或 Star 關(guān)注更新...

    summerpxy 評論0 收藏0

發(fā)表評論

0條評論

閱讀需要支付1元查看
<