- Express 是一個(gè)Node.js的基礎(chǔ)框架磷蛹,主要基于 Connect 中間件,并且自身封裝了路由(需要配合bodyParser)溪烤、視圖處理等功能味咳,使用人數(shù)眾多,弊端是callback回調(diào)方式檬嘀。
- Koa 是一個(gè)比Express更精簡(jiǎn)槽驶,使用node新特性的中間件框架。其提供的是一個(gè)架子鸳兽,而幾乎所有的功能都需要由第三方中間件完成掂铐,比如koa-router, koa-view等。
Koa 利用 co 作為底層運(yùn)行框架,利用 Generator 的特性全陨,實(shí)現(xiàn)“無(wú)回調(diào)”的異步處理
1.處理路由
Express :
使用 express.Router 類來(lái)創(chuàng)建可安裝的模塊化路由處理程序爆班。Router 實(shí)例是完整的中間件和路由系統(tǒng),以下示例將路由器創(chuàng)建為模塊辱姨,在其中裝入中間件柿菩,定義一些路由,然后安裝在主應(yīng)用程序的路徑中雨涛。
var express = require('express');
var router = express.Router();
router.use(function timeLog(req, res, next) {
console.log('Time: ', Date.now());
next();
});
// define the home page route
router.get('/', function(req, res) {
res.send('Birds home page');
});
// define the about route
router.get('/about', function(req, res) {
res.send('About birds');
});
module.exports = router;
接著枢舶,在應(yīng)用程序中裝入路由器模塊:
var routes = require('./route');
...
app.use('/route', routes);
Koa
路由處理 Express 是自身集成的,而 Koa 需要引入中間件
var koa = require('koa')
var route = require('koa-route') //中間件
var app = koa()
app.use(route.get('/', function *(){
this.body = 'Hello World'
}))
2.HTTP Request
兩個(gè)框架都封裝了HTTP Request對(duì)象镜悉,有一點(diǎn)不同是 Koa v1 使用 this 取代 Express 的 req祟辟、res。
Express:
var app = require('express')()
app.get('/room/:id', function (req, res) {
console.log(req.params)
})
// 獲取POST數(shù)據(jù)需要 body-parser 中間件
var bodyParser = require('body-parser')
app.use(bodyParser.json())
app.post('/sendgift', function (req, res) {
console.log(req.body)
})
Koa:
var app = require('koa')()
var route = require('koa-route')
app.use(route.get('/room/:id', function *() {
console.log(this.req.query)
}))
// 獲取POST數(shù)據(jù)需要 co-body 中間件
var parse = require('co-body')
app.use(route.post('/sendgift', function *() {
var post = yield parse(this.request)
console.log(post)
}))
3.區(qū)別
1.異步流程控制
Express 采用 callback 來(lái)處理異步侣肄,Koa v1 采用 generator旧困,Koa v2 采用 async/await。
2.錯(cuò)誤處理
Express 使用 callback 捕獲異常稼锅,對(duì)于深層次的異常捕獲不了吼具,
Koa 使用 try catch,能更好地解決異常捕獲矩距。
// Express callback
app.use(function (err, req, res, next) {
console.error(err.stack)
res.status(500).send('Something broke!')
})
// Koa generator
app.use(function *(next) {
try {
yield next
} catch (err) {
this.status = err.status || 500
this.body = { message: err.message }
this.app.emit('error', err, this)
}
})
// Koa async/await
app.use(async (ctx, next) => {
try {
await next()
} catch (err) {
ctx.status = err.status || 500
ctx.body = { message: err.message }
ctx.app.emit('error', err, this)
}
})
3.中間件處理
Express中app.use就是往中間件數(shù)組中塞入新的中間件拗盒,中間件處理方式是線性的,next過(guò)后繼續(xù)尋找下一個(gè)中間件锥债。
一個(gè)請(qǐng)求進(jìn)來(lái)經(jīng)過(guò)一系列中間件處理后再響應(yīng)給用戶陡蝇,清晰明了。
缺點(diǎn):基于 callback 組合業(yè)務(wù)邏輯哮肚,業(yè)務(wù)邏輯復(fù)雜時(shí)嵌套過(guò)多登夫,異常捕獲困難。
Koa的中間件處理方式是一個(gè)洋蔥模型允趟,koa處理完中間件后還會(huì)回來(lái)走一趟恼策,這就給了我們更加大的操作空間。
const Koa = require('koa');
const app = new Koa();
// x-response-time
app.use(async (ctx, next) => {
const start = Date.now();
await next();
const ms = Date.now() - start;
ctx.set('X-Response-Time', `${ms}ms`);
});
// logger
app.use(async (ctx, next) => {
const start = Date.now();
await next();
const ms = Date.now() - start;
console.log(`${ctx.method} ${ctx.url} - ${ms}`);
});
// response
app.use(async ctx => {
ctx.body = 'Hello World';
});
當(dāng)koa處理中間件遇到await next()的時(shí)候會(huì)暫停當(dāng)前中間件進(jìn)而處理下一個(gè)中間件潮剪,最后再回過(guò)頭來(lái)繼續(xù)處理剩下的任務(wù)