KOA2

基于 Node.js 平台的Web服务器框架

由 Express 原班人马打造

Express Koa , Koa2 都是 Web 服务器的框架,他们之间的差别和关系可以通过下面这个表格表示出

框架名 作用 异步处理
Express web 框架 回调函数
Koa web 框架 Generator+yield
Koa2 web 框架 async/await

环境依赖  Node v7.6.0 及以上

由于 Koa2 它是支持 async 和 await ,所以它对 Node 的版本是有要求的,它要求 Node 的版本至少是在7.6级以上,因为语法糖 async和await 是在 Node7.6 版本之后出现才支持

洋葱模型的中间件

 

 

 

这种中间件可能还不仅仅只有一个,可能会存在多个,比如上图所示, 它就存在三层中间件,这三层中间件在处理请求的过程以及它调用的顺序为:

  • 当一个请求到达咱们的服务器,最先最先处理这个请求的是第一层中间件
  • 第一层的中间件在处理这个请求之后,它会把这个请求给第二层的中间件
  • 第二层的中间件在处理这个请求之后,它会把这个请求给第三层的中间件
  • 第三层中间件内部并没有中间件了, 所以第三层中间件在处理完所有的代码之后,这个请求又会到了第二层的中间件,所以第二层中间件对这个请求经过了两次的处理,第二层的中间件在处理完这个请求之后,又到了第一层的中间件, 所以第一层的中间件也对这个请求经过了两次的处理

这个调用顺序就是洋葱模型, 中间件对请求的处理有一种先进后出的感觉,请求最先到达第一层中间件,而最后也是第一层中间件对请求再次处理了一下

KOA2的使用

步骤:

1>检查 Node 的版本

node -v 的命令可以帮助我们检查 Node 的版本,  Koa2 的使用要求 Node 版本在7.6及以上

 

 

 2>安装 Koa2

这个命令可以快速的创建出 package.json 的文件, 这个文件可以维护项目中第三方包的信息

npm init -y

这个命令可以在线的联网下载最新版本 koa 到当前项目中, 由于线上最新版本的 koa 就是koa2 , 所以我们并不需要执行 npm install koa2

npm install koa

3>编写入口文件 app.js

  3.1>创建 Koa 的实例对象

// 创建koa对象
const Koa = require('koa') // 导入构造方法
const app = new Koa() // 通过构造方法, 创建实例对象

  3.2>编写响应函数(中间件)

响应函数是通过use的方式才能产生效果, 这个函数有两个参数, 一个是 ctx ,一个是 next

  • ctx :

  上下文, 指的是请求所处于的Web容器,我们可以通过 ctx.request 拿到请求对象, 也可以通过 ctx.response 拿到响应对象

  • next :

  内层中间件执行的入口

// 编写响应函数(中间件)
app.use((ctx, next) => {
 console.log(ctx.request.url)
 ctx.response.body = 'hello'
})

4>指明端口号 

通过 app.listen 就可以指明一个端口号

// 绑定端口号 3000
app.listen(3000,function(){
    console.log("监听3000端口") 
})

5>启动服务器

通过 node app.js 就可以启动服务器了

KOA2中间件的特点

  • Koa2 的实例对象通过 use 方法加入一个中间件
  • 一个中间件就是一个函数,这个函数具备两个参数,分别是 ctx 和 next
  • 中间件的执行符合洋葱模型
  • 内层中间件能否执行取决于外层中间件的 next 函数是否调用
  • 调用 next 函数得到的是 Promise 对象, 如果想得到 Promise 所包装的数据, 可以结合 await 和async
app.use(async (ctx, next) => {
  // 刚进入中间件想做的事情
  await next()
  // 内层所有中间件结束之后想做的事情
})

 案例:

//创建koa对象
const koa=require("koa")
const app=new koa()
//编写响应函数(中间件)
app.use((ctx,next)=>{
    //ctx表示上下文,web容器,ctx.request  ctx.response
    //next下一个中间件,下一层中间件是否能够执行,取决于next函数有没有被调用
    console.log("第一层中间件");
    ctx.response.body="hello"
    next()
})
//第二层中间件
app.use((ctx,next)=>{
    console.log("第二层中间件");
    next()
})
//第三层中间件
app.use((ctx,next)=>{
    console.log("第三层中间件");
})
//绑定端口3000
app.listen(3000,()=>{
    console.log("监听3000端口")
})

 在这里为什么会输出两次呢?

这里是因为洋葱模型导致的,中间件的处理请求的过程以及它调用的顺序

我们这样看

//创建koa对象
const koa=require("koa")
const app=new koa()
//编写响应函数(中间件)
app.use((ctx,next)=>{
    //ctx表示上下文,web容器,ctx.request  ctx.response
    //next下一个中间件,下一层中间件是否能够执行,取决于next函数有没有被调用
    console.log("第一层中间件第一次");
    next()
    console.log("第一层中间件第二次");

})
//第二层中间件
app.use((ctx,next)=>{
    console.log("第二层中间件第一次");
    next()
    console.log("第二层中间第二次")
})
//第三层中间件
app.use((ctx,next)=>{
    console.log("第三层中间件第一次");
    console.log("第三层中间件第二次");

})
//绑定端口3000
app.listen(3000,()=>{
    console.log("监听3000端口")
})

 

 我们也可以第三层中间中return一个字符串,在第二层接收并输出

//第二层中间件
app.use((ctx,next)=>{
    console.log("第二层中间件第一次");
    const ret=next()
    console.log(ret)
    console.log("第二层中间第二次")
})
//第三层中间件
app.use((ctx,next)=>{
    console.log("第三层中间件第一次");
    console.log("第三层中间件第二次");
    return "end"

})

 

 此时返回Primise{'end'}

所以,next()并不是下一层中间件的指向,其内部还做了一部分分装,他把内层中间件return的字符串包装秤Primise对象,此时我们可以获取这个字符串

//第二层中间件
app.use(async(ctx,next)=>{
    console.log("第二层中间件第一次");
    const ret=await next()
    console.log(ret)
    console.log("第二层中间第二次")
})

在next()的前面加上await,此时我们就可以获取这个字符串

 

 

我们看下面的案例

//创建koa对象
const koa=require("koa")
const app=new koa()
//编写响应函数(中间件)
app.use((ctx,next)=>{
    //ctx表示上下文,web容器,ctx.request  ctx.response
    //next下一个中间件,下一层中间件是否能够执行,取决于next函数有没有被调用
    console.log(ctx.request.url);
    ctx.response.body="hello"
})
//绑定端口3000
app.listen(3000,()=>{
    console.log("监听3000端口")
})

 

 此时这里会输出两次

第一次输出“/”,这是我们在输入url地址之后回车输出的

/favicon.ico是网站头像,就是这个

 

posted @ 2021-11-11 22:03  keyeking  阅读(426)  评论(0编辑  收藏  举报