基于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 条评论
登录 后参与评论

相关文章

来自专栏马洪彪

C#爬虫系列(一)——国家标准全文公开系统

网上有很多Python爬虫的帖子,不排除很多培训班借着AI的概念教Python,然后爬网页自然是其中的一个大章节,毕竟做算法分析没有大量的数据怎么成。 C#相比...

680100
来自专栏吴伟祥

文件拷贝工具 原

WinSCP是一个Windows环境下使用SSH的开源图形化SFTP客户端。同时支持SCP协议。它的主要功能就是在本地与远程计算机间安全的复制文件。.winsc...

13930
来自专栏北京马哥教育

基础拾遗--【转】什么是长连接、短连接?

什么是长连接,什么是短连接? 贴个经典的,看完了就应该没啥问题了 : TCP/IP通信程序设计的丰富多样性 刚接触TCP/IP通信设计的人根据范例可...

33090
来自专栏吴伟祥

RESTful接口入门 转

从下面的图片可以看出,当我们需要把相同的数据展示到不同的界面上时,提供一个可以访问后台的接口,前台只负责将数据友好的,华丽的展示出来即可。而不需要为每一个前台都...

14230
来自专栏个人分享

用CRT connect MongoDB 使用Backspace无效

使用./mongo 10.1.235.62:27017 连接上后 打错了无法删除!? 这是在逗我,那就修改CRT个设置,点击选项,会话选项,仿真,把终端改成Li...

9720
来自专栏程序员宝库

vue-cli 脚手架中 webpack 配置基础文件详解

vue-cli是构建vue单页应用的脚手架,输入一串指定的命令行从而自动生成vue.js+wepack的项目模板。这其中webpack发挥了很大的作用,它使得我...

32230
来自专栏同步博客

掀开断点续传那一层面纱(下载篇)

  这一篇文章主要介绍的是http协议下载时的断点续传,详细到各个步骤。主要步骤有:DNS查找、TCP三次握手、http请求发送、TCP协议数据传输、暂停后的状...

17140
来自专栏张善友的专栏

分布式文件存储的数据库开源项目MongoDB

MongoDB是一个基于分布式文件存储的数据库开源项目。由C++语言编写。旨在为WEB应用提供可护展的高性能数据存储解决方案。 它的特点是高性能、易部署、易使用...

40390
来自专栏SDNLAB

OpenDaylight ping模块开发及分析

编者按:OpenDaylight ping模块开发及当ping操作触发数据流,对其进行分析及流程原理的疏通讲解,并在开发过程中遇到的问题进行总结,希望给大家能够...

36760
来自专栏JetpropelledSnake

Python入门之logging日志模块以及多进程日志

本篇文章主要对 python logging 的介绍加深理解。更主要是 讨论在多进程环境下如何使用logging 来输出日志, 如何安全地切分日志文件。 1. ...

1.3K70

扫码关注云+社区

领取腾讯云代金券