首先我们要搞清楚我们使用koa框架到底要干一件什么事情
我们要干的事情就是前端向服务器发送HTTP请求来获取数据,我们要能在Koa中接收到该HTTP请求,并作处理,然后将数据返回。那么如何接收HTTP请求呢,这个时候就要用到koa中的中间件的概念。

乍一听,有点懵圈,中间件是个什么鬼东西,莫慌莫慌,大家只需要把它理解成一个函数就完事了,编写一个中间件,就和你编写一个函数是一样的

举个最简单的例子
你想前端在发送http请求之后调用一个你自己写的函数如下(随便建立一个js文件,文件名大家自己可以随意起,我这个地方的文件名叫做app.js)

const Koa = require('koa') //将安装的koa包导入到当前文件中const app = new Koa()   //实例化一个koa应用程序对象function test(){console.log('hello,yu')
}

我们要做的首先就是要把这个test函数注册到koa应用程序对象上,那么如何注册呢,也很简单

const Koa = require('koa') //将安装的koa包导入到当前文件中const app = new Koa()   //实例化一个koa应用程序对象function test(){console.log('hello,yu')
}app.use(test)        //将test函数注册到koa应用程序对象上

这样我们编写的函数function就变成一个中间件,等待下次发起http请求的时候就可以执行了,是不是很简单!
但是通常情况下我们是不会把我们写的这样一个函数的函数名注册到koa里面的,我们一般是直接这样写

const Koa = require('koa') //将安装的koa包导入到当前文件中const app = new Koa()   //实例化一个koa应用程序对象app.use(()=>{console.log('hello,yu')
})                                    //将函数注册到koa应用程序对象上

这种写法是和上面的那种写法是完全等效的。(上面的箭头函数的写法是ES6的基础,不懂得请自行恶补ES6)我们在终端中输入命令node app.js ,你会发现打印出了hello,yu

那么问题又来了,一个应用应用程序对象上面只能有一个中间件吗?当然肯定不是的呀,一个应用程序对象是可以注册多个中间件的,接着上面的例子,我们再注册一个(当然你也可以注册好多个)

const Koa = require('koa') //将安装的koa包导入到当前文件中const app = new Koa()   //实例化一个koa对象app.use(()=>{console.log('hello,yu')
})                                    //将函数注册到koa应用程序对象上app.use(()=>{console.log('hello,yuyu')          //再注册一个中间件
})

当我们调用的时候,你发现怎么只打印出了上面那个,下面那个怎么没有打印出来,这是为森么呢,这是因为上面的那个是先注册的,下面的那个是后注册的,在koa中它只会自动帮你执行第一个中间件,后续的它都不管的,后面的中间件都需要开发者自己去调用的,那我们如何能够确保我们注册在应用程序对象上的中间件都能执行呢?koa已经帮我们想好啦,koa在执行每一个中间件的时候都会给这个中间件的函数传递两个参数,第一个为ctx(koa中叫上下文),第二个为next(就是指下一个中间件函数),这两个参数是由koa内部的机制帮我们自动传入的,不需要我们开发者自己管理的。我们刚刚不是只调用了第一个吗,这个时候我们只要用next就可以进行第二个的调用啦,我们只需要在

const Koa = require('koa') //将安装的koa包导入到当前文件中const app = new Koa()   //实例化一个koa对象app.use((ctx,next)=>{console.log('hello,yu')next()                             //调用下一个中间件函数
})                                    //将函数注册到koa应用程序对象上app.use((ctx,next)=>{console.log('hello,yuyu')
})

这个时候我们就能打印出两个函数中的内容啦。这样就完事啦!基本上koa的所有编程都是围绕着ctxnext两个东西展开的。
看起来是不是很简单,是不是就像是两个函数之间的相互调用一样。
接下来我们让这个中间件变得稍微复杂一点

const Koa = require('koa') //将安装的koa包导入到当前文件中const app = new Koa()   //实例化一个koa对象app.use((ctx,next)=>{console.log('1')next()console.log('2')
})                                    //将函数注册到koa应用程序对象上app.use((ctx,next)=>{console.log('3')next()console.log('4')
})

我们大胆猜测一下打印的顺序是啥,是不是不难猜出顺序是1、3、4、2,我们执行之后发现是没错的,至于说为啥3完了之后是4呢,因为我们只定义了两个,第二个中间件找不到下一个中间件,所以第二个中间件的next这个地方可以先忽略。那么这个简单的函数示例就印证了koa著名的洋葱模型啦。
每个中间件函数被next分割成了上半部分和下半部分,当一个请求进来之后先执行fun1的上半部分,接着是fun2的上半部分,再然后是fun2的下半部分,最后是fun1的下半部分,这就是所谓的洋葱模型,网上也有很多资料,随便给大家找了张图
那么next返回的究竟是一个什么东西我们可以打印看一下

const Koa = require('koa') //将安装的koa包导入到当前文件中const app = new Koa()   //实例化一个koa对象app.use((ctx,next)=>{const a = next()console.log(a)
})                                    //将函数注册到koa应用程序对象上app.use((ctx,next)=>{next()
})

我们会发现a是一个promise对象,但是里面是undefined,为啥呢,这是因为第二个中间件没有返回任何的值给第一个中间件,我们稍微做一下改动

const Koa = require('koa') //将安装的koa包导入到当前文件中const app = new Koa()   //实例化一个koa对象app.use((ctx,next)=>{const a = next()console.log(a)
})                                    //将函数注册到koa应用程序对象上app.use((ctx,next)=>{next()return '123'
})

这个时候a的值就变成了Promise{‘123’}了,这个字符串123被强制包装成了一个promise,所以说中间件之间的调用总会会返回一个pormise。
那么问题又来了,我们有时候就想要接收到的结果就直接是我返回的字符串123,而不是被包装过的promise{‘123’},那这个时候就用到了async和await
我们只要将代码改成

app.use(async(ctx,next)=>{const a = await next()console.log(a)
})                                    //将函数注册到koa应用程序对象上app.use((ctx,next)=>{next()return '123'
})

这样我们就可以直接获取到字符串123啦
这也就是为啥大家在网上搜索资料的时候都会发现中间件的写法是这样的

app.use(async(ctx,next)=>{console.log('3')await next()console.log('4')
})

不难看出,在函数名前面加了async,在next前面加了await,如果大家不想深入的知道为什么要加,大家只需要记住必须要这么写,这样能确保你在写中间件的时候是万无一失的,记死就完事了。
下面说一下为啥子,我们在使用nodejs编程的时候,绝大多数都是异步编程,强制在中间件加上async和await能保证所有的中间件都是按照洋葱模型执行的。那么肯定有人又要问了,为啥一定要按照洋葱模型执行,这个肯定是有原因呀,不然洋葱模型设计出来干嘛,。。
假设我们在第一个中间件函数里面要执行一段逻辑代码,它有个前提条件,必须要等后面全部的中间件函数执行完毕之后它才调用(最常见的比如说定时器),这个时候我们怎么保证后面的中间件函数执行完毕呢,这个时候不就用到洋葱模型了。如果不加async和await,可能就会导致你的代码在执行过程中出现某些错误。解释完毕。

在上面我们仅仅谈到了next,下面我们说一下ctx的用法。假设第一个中间件函数要接收第二个中间件函数传递给它的一些参数,正常情况下是不是将参数return回去就可以了,这样写当然没毛病,但是这样的传参方式是有局限性的,这个局限性在于如果几个中间件都是你自己编写的,你能够完全掌控这些中间件之间的调用顺序,确实这样写是没啥毛病的,但是在实际的开发工作中,我们常常会用到一些第三方的中间件,这些第三方的中间件,你是啷个知道它的调用顺序的耶,那这个时候的传参,就肯定不能用return了是不。

举个例子,我用了三个中间件,第一个中间件和第三个中间件都是自己写的,第二个中间件是调用了第三方的,我现在第一个中间件要获取到第三个里面的参数,ok,你第三个中间件return回参数没毛病给第二个中间件,但你第二个中间件啷个return给第一个中间件呢?你又没办法修改第三方的代码,这个时候ctx就光荣登场了,我们只需要把第三个中间件的参数绑定到ctx上,如下

const Koa = require('koa') //将安装的koa包导入到当前文件中const app = new Koa()   //实例化一个koa对象app.use(async(ctx,next)=>{await next()const r = ctx.r console.log(r)
})                                    //将函数注册到koa应用程序对象上app.use(async(ctx,next)=>{await next()ctx.r = 'abc'
})

这样就可以啦,但是这样的传值方式务必要保证中间件是执行顺序是按照洋葱模型来执行的,这就呼应到了上面说的在写中间件的时候一定要在函数名前面加asyncnext前面一定要加await,如果你要是不相信,你把第一个中间件的awaitasync取消掉,你可以看看打印出来的是啥,你验证之后就会发现打印出来的是undefined

好啦,今天就先写在这里啦~

koa2中间件个人理解相关推荐

  1. koa2 中间件里面的next到底是什么

    koa2短小精悍,女人不爱男人爱. 之前一只有用koa写一点小程序,自认为还吼吼哈,知道有一天某人问我,你说一下 koa或者express中间件的实现原理.然后我就支支吾吾,好久吃饭都不香. 那么了解 ...

  2. 关于koa2中间件的运行演示

    关于koa2中间件的运行演示 看演示代码: const Koa = require('koa'); const app = new Koa();app.use(async (ctx, next) =& ...

  3. nodejs开发 过程中express路由与中间件的理解 - pyj063 - 博客园

    nodejs开发 过程中express路由与中间件的理解 nodejs开发 express路由与中间件 路由 通常HTTP URL的格式是这样的: http://host[:port][path] h ...

  4. dotNET Core 3.X 请求处理管道和中间件的理解

    理解 dotNET Core 中的管道模型,对我们学习 dotNET Core 有很大的好处,能让我们知其然,也知其所以然,这样在使用第三方组件或者自己写一些扩展时,可以避免入坑,或者说避免同样的问题 ...

  5. Koa2 中间件原理解析

    原文出自:https://www.pandashen.com 前言 Koa 2.x 版本是当下最流行的 NodeJS 框架,Koa 2.0 的源码特别精简,不像 Express 封装的功能那么多,所以 ...

  6. laravel框架cookie应用到中间件的理解

    昨天博主接到一个委托的需求,大数据同事想要在请求日志抓取数据,希望在我的每个页面进行cookie的种植,方便他们进行定位分析,我思考了一下,简单呀,首先考虑的是通过中间件进行cookie种植,但是随后 ...

  7. 年末的大厂前端面试总结(20届双非二本)-终入字节

    关注若川视野, 回复"pdf" 领取资料,回复"1",可加群长期交流学习 自我介绍 双非二本,软件工程,自学前端,今年毕业. 喜欢编程,古风,日语和英语. 常以 ...

  8. koa2异常处理_koa2 中的错误处理以及中间件设计原理

    其实这不是一个问题,因为就 koa2 而言,他已经帮我做好了统一错误处理入口 app.onerror 方法. 我们只要覆盖这个方法,就可以统一处理包括 中间件,事件,流 等出现的错误. 但我们始终会看 ...

  9. Koa2和Redux中间件源码研究

    一.Koa2中间件源码分析 在Koa2中,中间件被存放在一个数组中. 使用koa中,最常见的就是app.use(fn),use函数部分源码如下所示.首先中间件必须是个函数.若是generator函数, ...

最新文章

  1. 怎么判断间隙过渡过盈配合_什么是配合间隙过盈过渡配合
  2. 飘逸的python - property及实现lazy property
  3. windows加固方案
  4. 通过微软的cors类库,让ASP.NET Web API 支持 CORS
  5. C++阶段01笔记汇总【C++软件安装、C++初识、数据类型、运算符、程序流程结构、数组、函数、指针、结构体】
  6. Qt笔记-QSslSocket双向认证
  7. 从王者荣耀里我学会的前端新手指引
  8. 乐虎 尖叫_如果您想更快地尖叫! 为什么政府技术需要(很多)更好的治理
  9. bootstrap collapse 卡顿
  10. vue+koa2移动电商实战
  11. H5及H5页面是什么意思?如何制作H5页面?
  12. Matter协议特性解析(一) 支持非Matter协议,私有协议,Matter Bridge技术分析
  13. Either类java_怎样利用Either和Option进行函数式错误处理的示例
  14. VMware创建虚拟机时出现 network bot from intel e1000
  15. matlab与simulink结合,code-matlab 利用SIMULINK和M函数相结合的方式仿真BFSK 调制在 联合开发网 - pudn.com...
  16. js 根据日期的不同时间段,做问候语:中午好,下午好,早上好
  17. 【邢不行|量化小讲堂系列45-实战篇】关于股票市值:99%投资者不知道的坑,你知道吗?
  18. C语言编译出现give arg types警告问题
  19. 用视频快速了解XDOC
  20. 利用EMCP物联网云平台通过网口远程监控S7-200 Smart PLC云组态

热门文章

  1. 传统企业做好这些,在校招中不输大厂!offer数翻6倍经验分享
  2. python实现dem输出三维模型_python实现DEM数据的阴影生成的方法
  3. html侧边栏添加滚动条,侧边栏滚动条
  4. 《北京市政务服务领域区块链应用创新蓝皮书(第一版)》正式发布
  5. Pink老师前端笔记-CSS第六天
  6. node.js面试题
  7. 如今的滴滴就是当初的出租车,被挑战是必然
  8. C语言基本概念----类型
  9. Java的数据类型-基本类型和引用类型
  10. 普通人开抖音小店挣钱吗?2023最受欢迎副业,有需求的小白看过来