koa2是什么
框架
- 封裝原生代碼的 API
- 規(guī)范流程和格式
- 讓開發(fā)人員更加關(guān)注于業(yè)務(wù)代碼,提高開發(fā)效率
框架frame和庫lib的區(qū)別
- 框架是唯一的,庫就可以共存,即:一個項目中只能使用一個框架,但可以同時多個庫
- 框架關(guān)注全流程,庫關(guān)注單個功能
- 類比 Vue 和 lodash
什么是koa2
koa2 是 nodejs web server 框架
- 官網(wǎng)和文檔 https://koa.bootcss.com/
- 通過 async/await 語法【處理異步】高效編寫web server
- 中間件機制,能合理拆分業(yè)務(wù)代碼
單獨使用koa插件
- 初始化項目 npm init
- 安裝koa2 npm install koa --save
const Koa = require('koa') // 引入koa
const app = new Koa() // 實例化
app.use(async(ctx) => {
ctx.body = 'hello world'
})
app.listen(3000) // web server 監(jiān)聽的 3000端口
koa2環(huán)境搭建
- 全局安裝腳手架
npm install -g koa-generator - 查看版本
koa2 --version - 創(chuàng)建項目
koa2 test(test文件夾名稱) - 啟動項目
npm run dev - 訪問
localhost:3000
koa路由使用方式
- 創(chuàng)建路由
const router = require('koa-router')()
// 設(shè)置前綴
router.prefix('/api')
router.get('/list', function(ctx, next) {
ctx.body = 'api list'
})
router.post('/create', function(ctx, next) {
ctx.body = 'api create'
})
// 導出
module.exports = router
- app.js中引入路由
const comments= require('./routes/comments')
- app.js中注冊路由
app.use(comments.routes(), comments.allowedMethods())

image.png

image.png
koa2處理http請求
ctx 即 res 和 req的集合,用來處理接收和返回數(shù)據(jù)
-
ctx.query獲取get請求的參數(shù)集合
image.png -
ctx.request.body獲取post請求的參數(shù)集合
image.png ctx.body設(shè)置響應(yīng)數(shù)據(jù)
koa2中間件
1、為什么使用中間件
- 拆分業(yè)務(wù)模塊,使代碼清晰
- 統(tǒng)一使用中間件,使得各業(yè)務(wù)代碼都規(guī)范標準
- 擴展性好,易添加、易刪除.
2、koa2業(yè)務(wù)代碼都是中間件
- app.use(..)都屬于中間件, 所有的請求都會經(jīng)過中間件
- 路由也是中間件,只有滿足路由規(guī)則才會進入這個中間件
3、中間件規(guī)則
- 不管是什么類型的中間件(路由的或者自定義的),它都是一個async函數(shù)。async函數(shù)的第一個參數(shù)是ctx,第二個參數(shù)是next。
模擬登陸 中間件
app.js中添加中間件邏輯代碼
app.use(async(ctx, next) => {
const query = ctx.query
if (query.user === 'zhangsan') {
// 模擬登陸成功
await next() // 執(zhí)行下一個重甲件
} else {
// 登陸失敗
ctx.body = "請登錄"
}
})

image.png
user參數(shù)正確時

image.png
koa2洋蔥圈模型
- 中間件機制,是koa2的精髓
- 每個中間件都是async函數(shù)
- 中間件的運行機制,就像洋蔥圈
洋蔥圈模型和中間件模型的關(guān)系
- 中間件機制:業(yè)務(wù)模塊的劃分
- 洋蔥圈模型:中間件的執(zhí)行機制
- 兩者要分開來看,不要混在一起
代碼示例
// 演示 koa2 中間件的洋蔥圈模型
const Koa = require('koa')
const app = new Koa()
// logger
app.use(async (ctx, next) => {
await next() // 執(zhí)行下一個中間件
const rt = ctx.response.get('X-Response-Time') // 獲取 時間差
console.log(`${ctx.method} ${ctx.url} - ${rt}`)
})
// x-response-time
app.use(async (ctx, next) => {
const start = Date.now()
await next() // 執(zhí)行下一個中間件
const ms = Date.now() - start // 計算時間差,例如 80
ctx.set('X-Response-Time', `${ms}ms`) // 記錄/設(shè)置 時間差
})
// response
app.use(async (ctx, next) => {
ctx.body = 'Hello world'
})
app.listen(3000)
console.log('koa2 已經(jīng)開始監(jiān)聽 3000 端口')

