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:

初探就这样了,喜欢的点个赞。如果有疑问出入,欢迎交流。

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