专栏首页iKcamp基于Koa2搭建Node.js实战(含视频)☞ 中间件用法

基于Koa2搭建Node.js实战(含视频)☞ 中间件用法

中间件用法——讲解 Koa2 中间件的用法及如何开发中间件

文章

middleware 中间件

正是因为中间件的扩展性才使得 Koa 的代码简单灵活。

app.js 中,有这样一段代码:

app.use(async (ctx, next)=>{
  await next()
  ctx.response.type = 'text/html'
  ctx.response.body = '<h1>Hello World</h1>'  
})

它的作用是:每收到一个 http 请求,Koa 都会调用通过 app.use() 注册的 async 函数,同时为该函数传入 ctxnext 两个参数。而这个 async 函数就是我们所说的中间件。

下面我们简单介绍一下传入中间件的两个参数。

ctx

ctx 作为上下文使用,包含了基本的 ctx.requestctx.response。另外,还对 Koa 内部对一些常用的属性或者方法做了代理操作,使得我们可以直接通过 ctx 获取。比如,ctx.request.url 可以写成 ctx.url

除此之外,Koa 还约定了一个中间件的存储空间 ctx.state。通过 state 可以存储一些数据,比如用户数据,版本信息等。如果你使用 webpack 打包的话,可以使用中间件,将加载资源的方法作为 ctx.state 的属性传入到 view 层,方便获取资源路径。

next

next 参数的作用是将处理的控制权转交给下一个中间件,而 next() 后面的代码,将会在下一个中间件及后面的中间件(如果有的话)执行结束后再执行。

注意: 中间件的顺序很重要!

我们重写 app.js 来解释下中间件的流转过程:

// 按照官方示例
const Koa = require('koa')
const app = new Koa()

// 记录执行的时间
app.use(async (ctx, next) => {
  let stime = new Date().getTime()
  await next()
  let etime = new Date().getTime()
  ctx.response.type = 'text/html'
  ctx.response.body = '<h1>Hello World</h1>'
  console.log(`请求地址: ${ctx.path},响应时间:${etime - stime}ms`)
});

app.use(async (ctx, next) => {
  console.log('中间件1 doSoming')
  await next();
  console.log('中间件1 end')
})

app.use(async (ctx, next) => {
  console.log('中间件2 doSoming')
  await next();
  console.log('中间件2 end')
})

app.use(async (ctx, next) => {
  console.log('中间件3 doSoming')
  await next();
  console.log('中间件3 end')
})

app.listen(3000, () => {
  console.log('server is running at http://localhost:3000')
})

运行起来后,控制台显示:

server is running at http://localhost:3000

然后打开浏览器,访问 http://localhost:3000,控制台显示内容更新为:

server is running at http://localhost:3000
中间件1 doSoming
中间件2 doSoming
中间件3 doSoming
中间件3 end
中间件2 end
中间件1 end
请求地址: /,响应时间:2ms

从结果上可以看到,流程是一层层的打开,然后一层层的闭合,像是剥洋葱一样 —— 洋葱模型。

此外,如果一个中间件没有调用 await next(),会怎样呢?答案是『后面的中间件将不会执行』。

修改 app.js 如下,我们去掉了第三个中间件里面的 await

const Koa = require('koa')
const app = new Koa()

// 记录执行的时间
app.use(async (ctx, next)=>{
  let stime = new Date().getTime()
  await next()
  let etime = new Date().getTime()
  ctx.response.type = 'text/html'
  ctx.response.body = '<h1>Hello World</h1>'
  console.log(`请求地址: ${ctx.path},响应时间:${etime - stime}ms`)
});

app.use(async (ctx, next) => {
  console.log('中间件1 doSoming')
  await next();
  console.log('中间件1 end')
})

app.use(async (ctx, next) => {
  console.log('中间件2 doSoming')
  // 注意,这里我们删掉了 next
  // await next()
  console.log('中间件2 end')
})

app.use(async (ctx, next) => {
  console.log('中间件3 doSoming')
  await next();
  console.log('中间件3 end')
})

app.listen(3000, () => {
  console.log('server is running at http://localhost:3000')
})

重新运行代码后,控制台显示如下:

server is running at http://localhost:3000
中间件1 doSoming
中间件2 doSoming
中间件2 end
中间件1 end
请求地址: /,响应时间:1ms

与我们的预期结果『后面的中间件将不会执行』是一致的。

下一篇:我们将学习下如何响应浏览器的各种请求。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 如何在原生微信小程序中实现数据双向绑定

    官网:https://qiu8310.github.io/minapp/ 作者:Mora 在原生小程序开发中,数据流是单向的,无法双向绑定,但是要实现双向绑...

    iKcamp
  • 微信小程序教学第四章第三节(含视频):小程序中级实战教程:详情-功能完善

    增加 下一篇 的功能,我们需要在视图中绑定一个事件,来触发代码中的响应函数,此函数会调用接口,返回下一篇文章内容数据。

    iKcamp
  • 微信小程序教学第四章第三节(含视频):小程序中级实战教程:详情-功能完善

    详情 - 功能完善 本文配套视频地址: https://v.qq.com/x/page/f0555nfdi14.html 开始前请把 ch4-3 分支...

    iKcamp
  • 浅析asp .net core 中间件

    其实中间件这个概念来源于分布式,当然这是一个狭隘的概念了,现在中间件概念就非常广泛了。

    李明成
  • 使用责任链模式实现中间件功能

    其实中间件无非就相当于一个过滤器的东西,在框架中将 请求或者响应 进行一层层的过滤,实现这种功能最合适不过的就是责任链模式啦

    码缘
  • 多维度分析 Express、Koa 之间的区别

    Express 历史悠久相比 Koa 学习资料多一些,其自带 Router、路由规则、View 等功能,更接近于 Web FrameWork 的概念。Koa 则...

    用户1462769
  • echarts的学习(七)Koa2的快速上手

    一天不写程序难受
  • 【刷穿 LeetCode】24. 两两交换链表中的节点(中等)

    做有关链表的题目,有个常用技巧:添加一个虚拟头结点(哨兵),帮助简化边界情况的判断。

    宫水三叶的刷题日记
  • 【面试高频系列】既能考察对「数据结构」的掌握,还能考察对「递归函数」的设计 ...

    这是 LeetCode 上的「24. 两两交换链表中的节点」,难度为 Medium。

    宫水三叶的刷题日记
  • 组件库设计实战 - 复杂组件设计

    一个成熟的组件库通常都由数十个常用的 UI 组件构成,这其中既有按钮(Button),输入框(Input)等基础组件,也有表格(Table),日期选择器(Dat...

    Nealyang

扫码关注云+社区

领取腾讯云代金券