一、koa2
- 框架:封裝原生代碼的API,規(guī)范流程和格式,提高開發(fā)效率(讓開發(fā)更加關(guān)注業(yè)務(wù)代碼)
- 框架與庫(kù)的區(qū)別:
(1)框架是唯一的,庫(kù)是可以共存
(2)框架關(guān)注全流程,庫(kù)關(guān)注單個(gè)功能
koa2是nodejs web server框架
(1)官網(wǎng):https://koa.bootcss.com/
(2)通過async/await語(yǔ)法高效編寫web server
(3)中間件機(jī)制,合理拆分業(yè)務(wù)代碼
(4)安裝:npm install koa --savekoa2體驗(yàn)
const Koa = require('koa')
const app = new Koa()
// contrxt =>ctx 聯(lián)系上下文
app.use(async (ctx)=>{
ctx.body = 'hellp world'
}).listen(3000) // web server 監(jiān)聽3000端口
- 環(huán)境搭建
(1)使用腳手架koa-generator創(chuàng)建koa2項(xiàng)目npm install -g koa-generator
(2)安裝完之后,使用命令koa2 --version或者koa2 -V檢測(cè)是否安裝成功,安裝成功出現(xiàn)版本號(hào),如下:安裝與測(cè)試圖片。


(3)創(chuàng)建koa2項(xiàng)目。執(zhí)行命令koa2 文件名 ,然后cd進(jìn)入創(chuàng)建好的文件夾。例:

(4)項(xiàng)目運(yùn)行 創(chuàng)建項(xiàng)目之后,本身有nodemon插件,直接使用
npm run dev運(yùn)行即可
(5)app.js中導(dǎo)出的app實(shí)列在bin下的www中引入
(6)www中監(jiān)聽的3000端口
(7)app.use后面引用的都是"中間件"
- 定義路由,設(shè)置問及那名:comment.js
(1)引入koa-router,例:const router = require('koa-router')()
(2)設(shè)置前綴
(3)輸出:module.exports = router //輸出
(4)使用``router.get`,整體可參考如下:
const router = require('koa-router')()
router.prefix('/api')// 前綴
// 定義路由:模擬獲取留言板列表
router.get('/list',async (ctx)=>{
ctx.body = "api list"
})
// 創(chuàng)建留言板的路由 ,注意:創(chuàng)建get請(qǐng)求用get,創(chuàng)建post請(qǐng)求用post
router.post('/create',async (ctx)=>{
ctx.body = 'api create'
})
module.exports = router //輸出
(5)創(chuàng)建好了路由,在app.js中先引入,然后注冊(cè)。,例:


(6)注冊(cè)里面的allowedMethods()是對(duì)于404 或者返回是空的情況的一種補(bǔ)充
二、koa2處理http請(qǐng)求
-
如何接收數(shù)據(jù)和返回?cái)?shù)據(jù):
ctx即:res和req的 集合
(1) 獲取querysting(url后面的參數(shù))
獲取querstring,字符串格式
獲取json格式的
(2)獲取request body



三、koa2中間件
-
什么是中間件:
(1)一個(gè)流程上,獨(dú)立的業(yè)務(wù)模塊
(2)可擴(kuò)展,可插拔
(3)類似于工廠的流水線
(4)如下,每一個(gè)功能模塊就是一個(gè)中間件
中間件 為什么使用使用中間件
(1)拆分業(yè)務(wù)模塊,使代碼更加清晰
(2)統(tǒng)一使用中間件,使各業(yè)務(wù)代碼都規(guī)范標(biāo)準(zhǔn)
(3)擴(kuò)展性好,易添加、易刪除所有的app.use(...)都是中間件、路由也是中間件(只不過限制了url的規(guī)則????);就是說,路由根據(jù)url的規(guī)則走
模擬登錄驗(yàn)證
// 模擬登錄(為了使用中間件)app.use所有操作都會(huì)經(jīng)過的
app.use(async (ctx, next) => { // next下一步,該use的下一個(gè)中間件,next
const query = ctx.query
if (query.user === 'zhangsan') {
//模擬登錄成功
await next() // 執(zhí)行下一步中間件 。await等待,等待異步執(zhí)行完,才會(huì)執(zhí)行完下面的代碼
} else {
// 模擬登錄失敗
ctx.body = '請(qǐng)登錄'
}
})
四、洋蔥圈模型
- 每個(gè)中間件都是async函數(shù)(函數(shù)運(yùn)行機(jī)制,沒講過。)
-
每一層洋蔥圈都是一個(gè)中間件(先進(jìn)入哪一個(gè)中間件,最后從那個(gè)中間件出)
洋蔥圈模型 - 回顧async/await
(1)await調(diào)用的時(shí)候,需要等當(dāng)前執(zhí)行完之后,才可以往下執(zhí)行。類似開發(fā)的時(shí)候,等待一個(gè)結(jié)果,必須拿到結(jié)果之后,才可以繼續(xù)使用執(zhí)行。
(2)fetch 原生api,一種HTTP數(shù)據(jù)請(qǐng)求的方式,是XMLHttpRequest的一種替代方案。類似與ajax,發(fā)送請(qǐng)求用的。所以外層調(diào)用的時(shí)候需要等待一個(gè)結(jié)果。
(3)代碼演示,不完整,只是一個(gè)執(zhí)行順序。
// 演示async await 的執(zhí)行順序
// 代碼放在瀏覽器中運(yùn)行。
// 加載一張圖片。使用async聲明函數(shù)。
async function getImg(url = '') {
await fetch(url)
// fetch 原生api,一種HTTP數(shù)據(jù)請(qǐng)求的方式,是XMLHttpRequest的一種替代方案。類似與ajax,發(fā)送請(qǐng)求用的
}
async function fn(){
const url = 'https://upload-images.jianshu.io/upload_images/19813229-97dc09156676ab94.png'
const start = Date.now() // 記錄當(dāng)前時(shí)間
await getImg(url) //調(diào)用getImg,加載圖片
// await調(diào)用的時(shí)候,進(jìn)入getImg函數(shù),等getImg函數(shù)執(zhí)行完之后(這行代碼才算執(zhí)行完),才會(huì)執(zhí)行下面的代碼
const ms = Date.now() - start // 計(jì)算時(shí)間差。
console.log(`加載圖片時(shí)間:${ms}`)
}
fn()
- 演示koa2中間件的洋蔥圈模型,代碼示例:
// 演示koa2中間件的洋蔥圈模型
const Koa = require('koa')
const app = new Koa()
// logger
app.use(async (ctx, next) => {
await next() // 執(zhí)行下一個(gè)中間件(對(duì)于當(dāng)前來說是x-response-time)
const rt = ctx.response.get('X-Response-Time') //res 。get獲取時(shí)間差
console.log(`${ctx.method} ${ctx.url} - ${rt}`)
})
// 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`) // X-Response-Time與上一個(gè)中間件res這里的要一致
// set 記錄/設(shè)置 時(shí)間差
})
// response
app.use(async (ctx, next) => {
ctx.body = 'Hello 洋蔥圈'
})
app.listen(3000)
console.log('監(jiān)聽3000端口')




