摘要:原本中的路由模塊已經(jīng)被移除,改為通過中間件的方式實(shí)現(xiàn)。的中間件就是函數(shù),可以是函數(shù),或是普通函數(shù),以下是官網(wǎng)的示例函數(shù)普通函數(shù)中間件可以通過官方維護(hù)的倉庫查找獲取,也可以根據(jù)需求編寫屬于自己的中間件。
Koa 是一個(gè)由 Express 原班人馬打造的新的 web 框架,Koa 本身并沒有捆綁任何中間件,只提供了應(yīng)用(Application)、上下文(Context)、請求(Request)、響應(yīng)(Response)四個(gè)模塊。原本 Express 中的路由(Router)模塊已經(jīng)被移除,改為通過中間件的方式實(shí)現(xiàn)。相比較 Express,Koa 能讓使用者更大程度上構(gòu)建個(gè)性化的應(yīng)用。1. 中間件簡介
Koa 是一個(gè)中間件框架,本身沒有捆綁任何中間件。本身支持的功能并不多,功能都可以通過中間件拓展實(shí)現(xiàn)。通過添加不同的中間件,實(shí)現(xiàn)不同的需求,從而構(gòu)建一個(gè) Koa 應(yīng)用。
Koa 的中間件就是函數(shù),可以是 async 函數(shù),或是普通函數(shù),以下是官網(wǎng)的示例:
// async 函數(shù) app.use(async (ctx, next) => { const start = Date.now(); await next(); const ms = Date.now() - start; console.log(`${ctx.method} ${ctx.url} - ${ms}ms`); }); // 普通函數(shù) app.use((ctx, next) => { const start = Date.now(); return next().then(() => { const ms = Date.now() - start; console.log(`${ctx.method} ${ctx.url} - ${ms}ms`); }); });
中間件可以通過官方維護(hù)的倉庫查找獲取,也可以根據(jù)需求編寫屬于自己的中間件。
2. 中間件原理 2.1 示例下面是一個(gè)的 Koa 應(yīng)用,簡單演示了中間件的執(zhí)行順序:
const Koa = require("Koa"); const app = new Koa(); // 最外層的中間件 app.use(async (ctx, next) => { await console.log(`第 1 個(gè)執(zhí)行`); await next(); await console.log(`第 8 個(gè)執(zhí)行`); }); // 第二層中間件 app.use(async (ctx, next) => { await console.log(`第 2 個(gè)執(zhí)行`); await console.log(`第 3 個(gè)執(zhí)行`); await next(); await console.log(`第 6 個(gè)執(zhí)行`); await console.log(`第 7 個(gè)執(zhí)行`); }); // 最里層的中間件 app.use(async (ctx, next) => { await console.log(`第 4 個(gè)執(zhí)行`); ctx.body = "Hello world."; await console.log(`第 5 個(gè)執(zhí)行`); }); app.listen(3000, () => { console.log(`Server port is 3000.`); })2.2 原理
從上面的示例中可以看出,中間件的執(zhí)行順序并不是從頭到尾,而是類似于前端的事件流。事件流是先進(jìn)行事件捕獲,到達(dá)目標(biāo),然后進(jìn)行事件冒泡。中間件的實(shí)現(xiàn)過程也是一樣的,先從最外面的中間件開始執(zhí)行,next() 后進(jìn)入下一個(gè)中間件,一路執(zhí)行到最里面的中間件,然后再從最里面的中間件開始往外執(zhí)行。
Koa 中間件采用的是洋蔥圈模型,每次執(zhí)行下一個(gè)中間件傳入兩個(gè)參數(shù) ctx 和 next,參數(shù) ctx 是由 koa 傳入的封裝了 request 和 response 的變量,可以通過它訪問 request 和 response,next 就是進(jìn)入下一個(gè)要執(zhí)行的中間件。
3. 編寫屬于自己的中間件 3.1 token 驗(yàn)證的 middleware前后端分離開發(fā),我們常采用 JWT 來進(jìn)行身份驗(yàn)證,其中 token 一般放在 HTTP 請求中的 Header Authorization 字段中,每次請求后端都要進(jìn)行校驗(yàn),如 Java 的 Spring 框架可以在過濾器中對 token 進(jìn)行統(tǒng)一驗(yàn)證,而 Koa 則通過編寫中間件來實(shí)現(xiàn) token 驗(yàn)證。
// token.js // token 中間件 module.exports = (options) => async (ctx, next) { try { // 獲取 token const token = ctx.header.authorization if (token) { try { // verify 函數(shù)驗(yàn)證 token,并獲取用戶相關(guān)信息 await verify(token) } catch (err) { console.log(err) } } // 進(jìn)入下一個(gè)中間件 await next() } catch (err) { console.log(err) } }
// app.js // 引入 token 中間件 const Koa = require("Koa"); const app = new Koa(); const token = require("./token") app.use(token()) app.listen(3000, () => { console.log(`Server port is 3000.`); })3.2 log 的 middleware
日志模塊也是線上不可缺少的一部分,完善的日志系統(tǒng)可以幫助我們迅速地排查出線上的問題。通過 Koa 中間件,我們可以實(shí)現(xiàn)屬于自己的日志模塊
// logger.js // logger 中間件 const fs = require("fs") module.exports = (options) => async (ctx, next) => { const startTime = Date.now() const requestTime = new Date() await next() const ms = Date.now() - startTime; let logout = `${ctx.request.ip} -- ${requestTime} -- ${ctx.method} -- ${ctx.url} -- ${ms}ms`; // 輸出日志文件 fs.appendFileSync("./log.txt", logout + " ") }
// app.js // 引入 logger 中間件 const Koa = require("Koa"); const app = new Koa(); const logger = require("./logger") app.use(logger()) app.listen(3000, () => { console.log(`Server port is 3000.`); })
可以結(jié)合 log4js 等包來記錄更詳細(xì)的日志
4. 總結(jié)至此,我們已經(jīng)了解中間件的原理,以及如何實(shí)現(xiàn)一個(gè)自己的中間件。
中間件的代碼通常比較簡單,我們可以通過閱讀官方維護(hù)的倉庫中優(yōu)秀中間件的源碼,來加深對中間件的理解和運(yùn)用。
本文首發(fā)于公眾號,更多內(nèi)容歡迎關(guān)注我的公眾號:阿夸漫談
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/101046.html
摘要:中異步處理在中使用的是,在中使用的是,我們本次采用來處理異步。函數(shù)參數(shù)為的數(shù)組,數(shù)組成員是通過方法添加的中間件。小結(jié)從最開始的編寫中間件,到現(xiàn)在閱讀函數(shù)源碼,中間件機(jī)制并不復(fù)雜,了解之后,我們可以運(yùn)用編寫更合適的中間件,構(gòu)建自己的應(yīng)用。 上一篇講了如何編寫屬于自己的 Koa 中間件,本篇將根據(jù)原理實(shí)現(xiàn)一個(gè)簡單的中間件處理函數(shù),并對 Koa 中間件處理函數(shù) compose 函數(shù)進(jìn)行源碼解...
摘要:系列教程,持續(xù)更新系列教程應(yīng)用初見系列教程處理靜態(tài)文件系列教程使用模板引擎系列教程路由控制中間件系列教程綜合搭建登錄注冊頁面系列教程實(shí)現(xiàn)登錄注冊功能這篇教大家如何使用模板引擎這里我們使用模板引擎做個(gè)例子,你們自己選擇自己熟練的模板引擎使用的 koa2系列教程,持續(xù)更新 koa2系列教程:koa2應(yīng)用初見 koa2系列教程:koa2處理靜態(tài)文件 koa2系列教程:koa2使用模板引擎 ...
摘要:我是一個(gè)知乎輕微重度用戶,之前寫了一只爬蟲幫我爬取并分析它的數(shù)據(jù),我感覺這個(gè)過程還是挺有意思,因?yàn)檫@是一個(gè)不斷給自己創(chuàng)造問題又去解決問題的過程。所以這只爬蟲還有登陸知乎搜索題目的功能。 我一直覺得,爬蟲是許多web開發(fā)人員難以回避的點(diǎn)。我們也應(yīng)該或多或少的去接觸這方面,因?yàn)榭梢詮呐老x中學(xué)習(xí)到web開發(fā)中應(yīng)當(dāng)掌握的一些基本知識。而且,它還很有趣。 我是一個(gè)知乎輕微重度用戶,之前寫了一只爬...
摘要:到此為止,我們就基本講清楚了中的中間件洋蔥模型是如何自動執(zhí)行的。 koa被認(rèn)為是第二代web后端開發(fā)框架,相比于前代express而言,其最大的特色無疑就是解決了回調(diào)金字塔的問題,讓異步的寫法更加的簡潔。在使用koa的過程中,其實(shí)一直比較好奇koa內(nèi)部的實(shí)現(xiàn)機(jī)理。最近終于有空,比較深入的研究了一下koa一些原理,在這里會寫一系列文章來記錄一下我的學(xué)習(xí)心得和理解。 在我看來,koa最核心...
摘要:最近練手開發(fā)了一個(gè)項(xiàng)目,是一個(gè)聊天室應(yīng)用。由于我們的項(xiàng)目是一個(gè)單頁面應(yīng)用,因此只需要統(tǒng)一打包出一個(gè)和一個(gè)。而就是基于實(shí)現(xiàn)的一套基于事件訂閱與發(fā)布的通信庫。比如說,某一個(gè)端口了,而如果端口訂閱了,那么在端,對應(yīng)的回調(diào)函數(shù)就會被執(zhí)行。 最近練手開發(fā)了一個(gè)項(xiàng)目,是一個(gè)聊天室應(yīng)用。項(xiàng)目雖不大,但是使用到了react, react-router, redux, socket.io,后端開發(fā)使用了...
閱讀 2029·2021-08-21 14:09
閱讀 492·2019-08-30 15:44
閱讀 2116·2019-08-29 16:32
閱讀 1380·2019-08-29 15:36
閱讀 3449·2019-08-29 12:43
閱讀 2786·2019-08-29 11:14
閱讀 438·2019-08-28 18:26
閱讀 2257·2019-08-26 13:57