node.js中koa和express的差異對比
前言
最近利用業(yè)余的時間,跟著 coderwhy 老師學習 node.js,了解以及掌握一些服務端的常見知識:
fileSystem:文件讀取模塊。events:事件流Buffer:node 中處理二進制的方式http 創(chuàng)建服務器Stream流的讀寫操作…
確實學習到了很多東西,填充了自己的知識體系的未知領域。
node.js 也許是前端開發(fā)者踏入服務端開發(fā)的最好選擇。同樣的 JavaScript,同樣的語法,以及同樣的你,基本上可以達到無縫銜接的開發(fā)。
對于 node.js 而言,社區(qū)里面出現(xiàn)了非常多的框架,快速上手,敏捷開發(fā)。
koa
和 express
就是其中的比較兩個突出的框架。
在閱讀下文之前,希望你掌握了 express 和 koa 的基本使用,不然下面內(nèi)容對你的幫助也許不是那么的大。
koa 和 express 的介紹
express 是一個基于 node.js 平臺,快速,開放,極簡的 web 開發(fā)框架。express 官網(wǎng)
koa 是基于 node.js 平臺的下一代 web 開發(fā)框架。koa 官網(wǎng)
兩個框架都是同一個團隊開發(fā)的,都是 node.js 中比較優(yōu)秀的框架。
都是 node.js 框架,同一個團隊為什么要開發(fā)兩個呢?
express 也許是 node.js 最早出的框架,里面集成了大量的中間件,造成了框架的笨重性。團隊領隊人 TJ 發(fā)現(xiàn)了 express 的設計是有缺陷的,如果想要修復這個設計缺陷,就會造成 express 的框架重構。
基于上面的種種原因(當然還有不知道的),就打算重新寫一個新的框架->koa,來實現(xiàn) express 的不足之處。
express 現(xiàn)在有團隊中的團員維護,基本上也很少更新了。
koa 由團隊領隊人 TJ 主要維護。
? --來自 coderwhy 老師的閑談
上面的閑談的內(nèi)容不重要,當個樂子開心一下就好了。
一起看看 express 和 koa 在 github 上的星標:
可以發(fā)現(xiàn) express 的使用率還是比 koa 高,盡管 express 笨重,設計有缺陷,但是對于開發(fā)者而言,當不考慮這些因素情況下,express 還是吃香的。
兩者都是同一團隊寫的兩個框架,那么核心的思想肯定是相同的,當然肯定會也存在差異,那么接下來就來重點比較一下其中的差異吧。
koa 和 express 的差異對比
下面主要從兩個方面來分析其中的差異:設計架構、中間件。
因為也是第一次接觸 koa (express 以前是接觸了的),如果存在有誤的地方,請指出來,虛心受教,共同進步。
koa 和 express 的設計架構對比
express 是完整和強大的,里面集成了大量的中間件,比如說:路由,靜態(tài)資源等中間件。對于開發(fā)者而言,技術統(tǒng)一,都是使用 express 內(nèi)部提供的。
koa 是靈活和自由的,基本上沒有集成任何中間件(核心代碼只有大致1600行左右),中間件都需要自己去安裝。對于開發(fā)者而言,選擇技術的類型是多樣的,豐富的。
webstorm 和 vscode 的使用,都是因人而異,沒有誰強誰弱。那么對于 express 和 koa 也是同樣的道理,各自有各自優(yōu)勢。
接下來我們一起來聽聽 express 和 koa 獨白:
express:hi,koa,我倆同處一體,我倆比比?
koa:???
express:我倆的發(fā)動機都是中間件
,我有三個兄弟:request
,response
,next
,你有幾個兄弟呢?
koa:額,我有兩個兄弟:context
,next
。不過我這 context
兄弟很厲害,以一敵二(request,response)。
express:我自帶路由(Router
),直接使用即可,你呢?
koa:安裝。(koa-router
或者 @dva/router
)
express:我可以自己暴露靜態(tài)資源,你呢?
koa:安裝。(koa-static
)
express:我只需要配置一下,就可以解析客戶端傳遞 application/json 的格式數(shù)據(jù),你呢?
koa:還是安裝。(koa-bodyparser
)
express:你能不能不要安裝呀,你就沒有自帶的?我還是只需要配置一下,就可以解析客戶端傳遞 x-www-form-urlencoded 的格式數(shù)據(jù),你呢?
koa:哈哈哈,不好意思,我不用配置,我也能解析 x-www-form-urlencoded 的格式數(shù)據(jù)。
koa:我還能安裝 @koa/multer
來實現(xiàn)文件上傳,你自帶了嗎?
express:額。。。我這個還真沒自帶,我也需要安裝 multer
來實現(xiàn)。
koa:讓你裝 xxx。你我本是同根生,相煎何太急,和平相處不行嘛。
express:。。。
TJ:莫吵了,把你倆創(chuàng)建出來,設計理念本就是不相同的。express 你走的完整路線,koa 走的是靈活路線,所以不用相互較勁,和氣生財。
koa 和 express 的中間件對比
express 和 koa 的核心,都是中間件。
簡單的來說,理解了中間件,也就理解了express 和 koa。
何為中間件?
那么何為中間件呢?
express 和 koa 都能創(chuàng)建一個服務器實例 app,那么給 app 傳入一個回調(diào)函數(shù),那么該回調(diào)函數(shù)就被稱為中間件(middleware)。
express 創(chuàng)建中間件:
// 方式一:use(fn) app.use((req, res, next) => {}) // 方式二:use(path, fn) app.use('/', (req, res, next) => {}) // 方式三:method(path, fn) app.get('/', (req, res, next) => {}) // 方式四:method(path, fn1, fn2, fn3) app.get('/', (req, res, next) => {}, (req, res, next) => {})
koa 創(chuàng)建中間件:
// 方式一:use(fn) app.use((ctx, next) => {}) // 方式二:use(path, fn) app.use('/', (ctx, next) => {})
在這里就不展開怎么使用中間件了,我相信你會的,express 和 koa 的中間件道理是相同的。
中間件的執(zhí)行順序(同步,異步)
express 同步
app.use((req, res, next) => { console.log("中間件01: next前"); next(); console.log("中間件01: next后"); }); app.use((req, res, next) => { console.log("中間件02: next前"); next(); console.log("中間件02: next后"); }); app.use((req, res, next) => { console.log("中間件03") });
express 異步
function mockAsync () { return new Promise((resolve) => { setTimeout(() => { resolve(321) }, 1000) }) } app.use((req, res, next) => { console.log("中間件01: next前"); next(); console.log("中間件01: next后"); }); app.use((req, res, next) => { console.log("中間件02: next前"); next(); console.log("中間件02: next后"); }); app.use(async (req, res, next) => { const data = await mockAsync() console.log("中間件03: next前"); });
koa 同步
app.use((ctx, next) => { console.log('中間件01: next前'); next() console.log('中間件01: next后'); }) app.use((ctx, next) => { console.log("中間件02: next前"); next(); console.log("中間件02: next后"); }); app.use((ctx, next) => { console.log("中間件03"); });
koa 異步
function mockAsync() { return new Promise((resolve) => { setTimeout(() => { resolve(321); }, 1000); }); } app.use((ctx, next) => { console.log('中間件01: next前'); next() console.log('中間件01: next后'); }) app.use((ctx, next) => { console.log("中間件02: next前"); next(); console.log("中間件02: next后"); }); app.use(async (ctx, next) => { const res = await mockAsync() console.log("中間件03"); });
上面四個案例,分別從:
- express 同步
- express 異步
- koa 同步
- koa 異步
來分析了中間的執(zhí)行順序,可以得出兩點結論:
- 無論是 express 還是 koa,當中間件是同步代碼并且調(diào)用了 next 函數(shù),那么程序運行就會先執(zhí)行每個中間件next函數(shù)之前的代碼,當執(zhí)行到最后一個中間件時,又會回滾執(zhí)行每個中間件next 函數(shù)后的代碼(類似于 數(shù)據(jù)結構中的 first in last out)。
- 無論是 express 還是 koa,當遇到中間件中存在異步代碼,就會停止向下執(zhí)行,而是回到上一個中間件繼續(xù)執(zhí)行。
所以對于 express 和 koa 在中間件執(zhí)行上,**表現(xiàn)形式**上是相同的。
而不相同之處就是在于 express 和 koa 在針對中間件存在異步代碼時,**處理方式**不同(簡單的來說也就是內(nèi)部的 next 函數(shù)實現(xiàn)不同)。
koa 和 express 不同的異步處理方式
假如存在這樣的一個案例:存在兩個中間件,一個是業(yè)務接口處理的中間件,一個是針對處理相同數(shù)據(jù)的中間件(比如:針對每個接口返回用戶信息),這里的獲取用戶信息,就是異步操作。
那么針對 express 會寫出以下代碼:
function getUserInfo () { return new Promise((resolve) => { setTimeout(() => { resolve({name: 'copyer', sex: 'man'}) }, 1000) }) } app.get('/list', (req, res, next) => { const list = [ { id: "1", content: "列表1" }, { id: "2", content: "列表2" }, ]; next(); res.json({ list, userInfo: req?.userInfo // 返回用戶信息,需要通過下個中間件來獲取 }) }); app.use(async (req, res, next) => { // mock 異步代碼,拿到用戶信息 const data = await getUserInfo(); console.log(data); // { name: 'copyer', sex: 'man' } req.userInfo = data; // 設置用戶信息 });
當我們訪問 list 接口時,發(fā)現(xiàn)是拿不到用戶信息(userInfo),因為遇到是異步函數(shù),就會停止繼續(xù)執(zhí)行下面的代碼,而是回到上一個中間件繼續(xù)執(zhí)行,所以沒有拿到用戶信息。
koa 也是同樣的道理,但是 koa 卻是可以解決這個問題。代碼如下:
function getUserInfo() { return new Promise((resolve) => { setTimeout(() => { resolve({ name: "copyer", sex: "man" }); }, 1000); }); } router.get('/list', async (ctx, next) => { const list = [ { id: "1", content: "列表1" }, { id: "2", content: "列表2" }, ]; await next(); /*****************重點代碼*********************/ ctx.body = { list, ctx: ctx?.userInfo } }); router.use(async (ctx, next) => { const res = await getUserInfo(); console.log(res); // { name: 'copyer', sex: 'man' } ctx.userInfo = res; // 設置用戶信息 }); app.use(router.routes())
看上面標記的重點代碼,那么就是處理異步的關鍵。在 next
執(zhí)行前面,加上一個 await
,這樣就能正常的拿到用戶信息。
await next()
的意思就是等待下個中間件執(zhí)行完成,那么這樣用戶信息也就設置成功了。
那么肯定有人這樣想,那么我在 express 調(diào)用 next 函數(shù)時,也加上 await ,是不是也解決了?想法很美好,但是行不通的。為撒?
express 中的 next 函數(shù),返回值一個void,沒有返回值。
這里的 next 函數(shù)接受一個參數(shù) err,也就是錯誤信息,針對全局異常處理的收集時,就會使用。
koa 中的 next 函數(shù),返回值一個Promise。
這里的 next 函數(shù)不接受參數(shù),所以全局錯誤的異常處理,需要另想它法。
koa 和 express 在異步處理函數(shù),最大的差別就是 next 函數(shù)實現(xiàn)不同,那么也就造成了中間件在異步上的使用不同。
koa 在上一個中間件拿取下一個異步中間件的數(shù)據(jù),然后返回。express 卻是不行,這是 express 設計上的缺陷。
洋蔥模型
想想平時生活中的洋蔥,是不是一層一層的。
中間件從上往下(從外往里),然后從下往上(從里往外)執(zhí)行,無論是同步還是異步都滿足,koa 是符合洋蔥模型的。
express 是在同步的時候是滿足洋蔥模型的,但是異步的時候卻是不能滿足洋蔥模型。
總結
這篇主要從設計架構和中間件兩個方面來解釋說明 express 和 koa 之間的差異。
比較差異并不是為了證明誰好誰弱,而是為了另一方面來充分認識框架隱藏的知識點,加深自己理解。
到此這篇關于node.js中koa和express的差異對比的文章就介紹到這了,更多相關koa和express對比內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
- Node.js中Express框架使用axios同步請求(async+await)實現(xiàn)方法
- node.js使用express-jwt報錯:expressJWT?is?not?a?function解決
- Node.js使用express寫接口的具體代碼
- Node.js?express中的身份認證的實現(xiàn)
- 使用Express+Node.js對mysql進行增改查操作?
- node.js三個步驟實現(xiàn)一個服務器及Express包使用
- Node.js中Express框架的使用教程詳解
- node.js+express留言板功能實現(xiàn)示例
- node.js使用express-fileupload中間件實現(xiàn)文件上傳
- Node.js+express+socket實現(xiàn)在線實時多人聊天室
- Express框架實現(xiàn)簡單攔截器功能示例
相關文章
node.js中的querystring.parse方法使用說明
這篇文章主要介紹了node.js中的querystring.parse方法使用說明,本文介紹了querystring.parse的方法說明、語法、接收參數(shù)、使用實例和實現(xiàn)源碼,需要的朋友可以參考下2014-12-12nodejs不用electron實現(xiàn)打開文件資源管理器并選擇文件
最近在開發(fā)一些小腳本,用 nodejs 實現(xiàn),其中很多功能需要選擇一個/多個文件,或者是選擇一個文件夾,這種情況下網(wǎng)上給出的解決方案都是 electron,但是我一個小腳本用 electron 屬實有點夸張了,后來轉念一想可以通過 powershell 來實現(xiàn)類似的功能,需要的朋友可以參考下2024-01-01node-red教程之dashboard簡介與輸入型儀表板控件的使用
Node-red支持自定義節(jié)點,當然也就支持自定義圖形化的節(jié)點。也有優(yōu)秀的開發(fā)者把自己建立的圖形化節(jié)點無償分享。這里給出一個股票界面的例子,讓大家看一看優(yōu)秀的node-red界面能做到什么樣子2022-01-01