koa2

一、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 --save

  • koa2體驗(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è)試圖片。
安裝

測(cè)試

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

創(chuàng)建項(xiàng)目

(4)項(xiàng)目運(yùn)行 創(chuàng)建項(xiàng)目之后,本身有nodemon插件,直接使用npm run dev運(yùn)行即可
image.png

(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è)。,例:


引入
注冊(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


js中代碼書寫
postman發(fā)送json數(shù)據(jù)

cmd結(jié)果

三、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端口')
過程
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容