KOA 初探 洋蔥模型

KOA 官網鏈接

當然,如果你有express的基礎就最好了,畢竟是原班人馬開發

常用的指令

npm install  koa
npm install nodemon
touch app.js
nodemon app.js

測試一

use

use 函數 使用中間件

app.js

const Koa = require('koa')

const app = new Koa()

app.use((ctx,next)=>{
  console.log(1)
  console.log(2)
})
app.use((ctx,next)=>{
  console.log(3)
  console.log(4)
})

app.listen(1019)
nodemon app.js  
// 瀏覽器運行localhst:1019  輸出
1
2

測試二

next()

next函數主要負責將控制權交給下一個中間件,如果當前中間件沒有終結請求,並且next沒有被調用,那麼當前中間件的請求將被掛起,等到next()後的中間件執行完再返回繼續執行。總結來說,就是:從第一個中間件開始執行,遇到next進入下一個中間件,一直執行到最後一箇中間件,在逆序,執行上一個中間件next之後的代碼,一直到第一個中間件執行結束才發出響應。如下代碼

const Koa = require('koa')

const app = new Koa()

app.use((ctx,next)=>{
  console.log(1)
  next()
  console.log(2)
})
app.use((ctx,next)=>{
  console.log(3)
  next() // 下一個中間件沒有 按下執行 4
  console.log(4)
})

app.listen(1019)
nodemon app.js
//輸出
1
3
4
2

這可以說是一個最最最基本的洋蔥模型,先進去再出來

在這裏插入圖片描述

測試三

const Koa = require('koa')

const app = new Koa()

app.use((ctx,next)=>{
  console.log(1)
  next() // 初次進入下個組件
  console.log(2)
})
app.use((ctx,next)=>{
  console.log(3)
  next() // 初次進入下個組件
  console.log(4)
})

app.use((ctx,next)=>{
  console.log(5)
  next() // 初次進入下個組件
  console.log(6)  // 沒有下個組件 再組件向上
})

app.listen(1019)
// 輸出
1
3
5
6
4
2

測試四

const Koa = require('koa')

const app = new Koa()

app.use((ctx,next)=>{
  console.log(1)
  const a = next()
  console.log(a)
  console.log(2)
})
app.use((ctx,next)=>{
  console.log(3)
  console.log(4)
})

app.listen(1019)
1
3
4
Promise { undefined } //因爲上一個中間件沒有返回值 ,如果return一個值,則有值 promise
2

如果對promise不太清楚的地方,可以點這裏 PromisePromise 與 異步機制

插一嘴,async 加在函數前,哪怕普通函數,也會強制轉換成promise對象。控制檯 輸出打印後會有undefined,說明一個線程結束

測試五

const Koa = require('koa')

const app = new Koa()

app.use((ctx,next)=>{
  console.log(1)
  const a = next()
  console.log(a)
  console.log(2)
})
app.use((ctx,next)=>{
  console.log(3)
  console.log(4)
  return "中間件可以return"
})

app.listen(1019)
1
3
4
Promise { '中間件可以return' }
2

案例六

async用於申明一個function是異步的,而await認爲是async wait 的簡寫,等待一個異步方法的完成。

const Koa = require('koa')

const app = new Koa()

app.use( async(ctx,next)=>{
  console.log(1)
  const a = await next() // 或者不用按async await .then((res)=>{})
  console.log(a)
  console.log(2)
})
app.use((ctx,next)=>{
  console.log(3)
  console.log(4)
  return "中間件可以return"
})

app.listen(1019)
1
3
4
中間件可以return
2

測試七

線程阻塞問題

測試七-1
const Koa = require('koa')

const app = new Koa()

app.use( async(ctx,next)=>{
  console.log(1)
  const a = await next()
  console.log(a)
})
app.use((ctx,next)=>{
  const axios = require('axios')
  const start = Date.now()
  const res = axios.get('http://www.baidu.com')
  const end = Date.now()
  console.log(end-start)
})

app.listen(1019)
// 輸出
1
1   // 這裏返回 0或者1或者2 幾乎可以忽略不計 不阻塞 可以認爲沒有等待上個axios.get()請求完成後再執行下一步
測試七-2
const Koa = require('koa')

const app = new Koa()

app.use( async(ctx,next)=>{
  console.log(1)
  const a = await next()
  console.log(a)
})
app.use(async(ctx,next)=>{
  const axios = require('axios')
  const start = Date.now()
  const res = await axios.get('http://www.baidu.com')
  const end = Date.now()
  console.log(end-start)
})

app.listen(1019)
1
110  耗時較多 阻塞
測試七-3
const Koa = require('koa')

const app = new Koa()

app.use( async(ctx,next)=>{
  console.log(1)
  next()
  console.log(2)
})
app.use(async(ctx,next)=>{
  console.log(3)
  const axios = require('axios')
  const res = await axios.get('http://www.baidu.com') //線程阻塞返回上一個組件
  next()
  console.log(4)
})

app.listen(1019)
// 返回沒有按照洋蔥模型執行
1
3
2
4

確保每個中間件按照洋蔥模型執行

async()=>{
	await next()
}
測試七-4
const Koa = require('koa')

const app = new Koa()

app.use( async(ctx,next)=>{
  console.log(1)
  await next()
  console.log(2)
})
app.use(async(ctx,next)=>{
  console.log(3)
  const axios = require('axios')
  const res = await axios.get('http://www.baidu.com')
  next()
  console.log(4)
})

app.listen(1019)
// 返回按照洋蔥模型執行
1
3
4
2

測試八

自己寫的中間件,return 傳遞數組,是沒有問題的。但是如果使用第三方插件,就不太方便了。所以koa使用了一個全局上下文對象ctx。類似於window,一個全局對象,你就會window.xx。

const Koa = require('koa')

const app = new Koa()

app.use( async(ctx,next)=>{
  console.log(1)
  await next()
  console.log(ctx.htmlData)
})
app.use(async(ctx,next)=>{
  console.log(3)
  const axios = require('axios')
  const res = await axios.get('http://www.baidu.com')
  ctx.htmlData = res
  next()
  console.log(4)
})

app.listen(1019)
// 百度的信息
   '<!DOCTYPE html>\n<!--STATUS OK--><html>\n<head>\n   
 \n    <meta http-equiv="content-type" content="text/html;charset=utf-8">\n    <meta http-equiv="X-UA-Compatible" content="IE=Edge">\n\t<meta content="always" name="referrer">\n  
  <meta name="theme-color" content="#2932e1">\n    <link rel="shortcut icon" href="/favicon.ico" type="image/x-icon" />\n    <link rel="search" type="application/opensearchdescription+xml" href="/content-search.xml" title="百度搜索" />\n    <link rel="icon" sizes="any" mask href="//www.baidu.com/img/baidu_85beaf5496f291521eb75ba38eacbd87.svg">\n\t\n\t\n\t<link rel="dns-prefetch" href="//s1.bdstatic.com"/>\n\t<link rel="dns-prefetch" href="//t1.baidu.com"/>\n\t<link rel="dns-prefetch" href="//t2.baidu.com"/>\n\t<link rel="dns-prefetch" href="//t3.baidu.com"/>\n\t<link rel="dns-prefetch" href="//t10.baidu.com"/>\n\t<link rel="dns-prefetch" href="//t11.baidu.com"/>\n\t<link rel="dns-prefetch" href="//t12.baidu.com"/>\n\t<link rel="dns-prefetch" href="//b1.bdstatic.com"/>\n    \n    <title>百度一下,你就知道</title>\n    \n\n<style id="css_index" index="index" type="text/css">html,body{height:100%}\nhtml{overflow-y:auto}\nbody{font:12px arial;text-align:;background:#fff}\nbody,p,form,ul,li{margin:0;padding:0;list-style:none}\nbody,form,#fm{position:relative}\ntd{text-align:left}\nimg{border:0}\na{color:#00c}\na:active{color:

初探就這樣了,喜歡的點個贊。如果有疑問出入,歡迎交流。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章