浅谈express.js框架中间件(middleware)


Posted in Javascript onApril 07, 2019

_express.js_作为_Node.js_的老牌框架,是现有框架中最全面的。然而在学习express除了那些api之外,对于框架最重要的就是__中间件__这个概念了。如果理解了,就可以把这个框架玩活了,项目开发肯定会更加顺利,而且还可以开发很多额外的功能,甚至中间件扩展开发。

但是就这么一个东西,是很多学习node.js的小萌新们就算写出一个博客项目,都不知道它到底有啥作用。我当时在理解的时候也花了不少功夫,趁着没有啥工作,给各位学习express.js的一点点我的指导意见。当然,这里面可能也有koa2和egg的忠实粉丝,但其实所有node框架貌似都有这个概念,所以我用express举例子,希望各位将就一下哈,应该都是可以看得懂的。

首先我先来一波官方的解释:

浅谈express.js框架中间件(middleware)

好吧,被这些英语吓到了,来一波译文:

[中间件函数是可以访问请求对象(req)、响应对象(res)和应用程序请求响应周期中的下一个函数的函数。下一个函数是Express路由器中的一个函数,当调用该函数时,它执行当前中间件之后的中间件。

中间件功能可以执行以下任务:

  • 执行任何代码
  • 对请求和响应对象进行更改。
  • 结束请求响应周期。
  • 调用堆栈中的下一个中间件。

终于知道当初的我为毛刚开始理解的时候很困难了,说实在的看得我真的有懵的。幸好,我还是从这个坑爬出来了,我来拉你们一把了。首先我们不去深究概念,直接上一个代码块。

浅谈express.js框架中间件(middleware)

如果我们启动服务,访问'/'路由,会返回"这是一个根路由",访问router1路由就会得到这是一个"这是一个router1路由的"的信息。这看起来是一个很简单的路由查询,我们理一下过程,这个请求是如何访问到这个路由的呢。

一般来说,一个express框架的项目会写入很多路由,但各位要注意的是,这个请求并不是直接定位到这个路由的,而是一个从上至下匹配的一个过程。

有点乱?没关系我们看图

浅谈express.js框架中间件(middleware)

我们看到这幅图,有一个箭头,从上到下的。什么意思呢,如果用户发了一个这样的请求

GET '/router7'

那么他会从第一个开始一个一个去匹配,知道发现有一个路由名和请求方法都一致的路由,就立马执行里面的代码,并且返回一段文字"这是一个router7路由"。这都很好理解,那么现在我有一个需求,就是不管访问任何一个路由,我都要知道这个访问者的ip地址和访问的目标路由打印出来,生产访问日志。那么怎么做了。

我们分析一波,这段程序是所有的请求都要执行的,如果按照执行顺序的说法,那么这段程序是应该放到所有路由的最前面的,也就是说这段程序是所有路由要经过的一段程序,也就是我们所说的中间件。好的,废话不多说,上代码

const fs = require('fs')
const log = (req,res) => {
  const ip = req.ip,
     route = req.route.path
  const log = `ip:${ip} path:${route}`
   fs.writeFileSync(__dirname + '/log',log)
}

比如现在我有一个log函数,它专门用来记录访问日志的。如何所有的都一起执行了,我们加一段这样的代码

app.use(log)

它加在所有代码的最上面,但是不是加上就完事了,还必须在log函数里面再加一段代码,不然当程序执行到里面之后就出不去了,什么代码了。我们重写log函数

const log = (req,res,next) => {
  const ip = req.ip,
     route = req.route.path
  const log = `ip:${ip} path:${route}`
   fs.writeFileSync(__dirname + '/log',log)
   next()
}

大家有没有看见那个next,它有什么作用了。前面我们提到,它其实就是一个过渡者,主要的作用其实就是经过之后,要继续往下面执行,还是就此终止返回结果。

说的简单一点,就是我们一个http请求,到达我们的node服务器之后,要经历的过程,而每经过一个程序块,就是个中间件,每一个中间件只要有next就会传递到下一个中间件里面,直到服务器res响应结果,整个路由就此结束。

我们整合一下代码。并且精简一下,也跑一遍程序

const express = require('express')
const app = express()

const log = (req,res,next) => {
  const ip = req.ip,
     route = req.route.path
  const log = `ip:${ip} path:${route}`
   fs.writeFileSync(__dirname + '/log',log)
   next()
}

app.use(log)//任何请求都会经过这个log中间件 

app.get('/', (req, res) => {
  console.log(req.route.stack)
  res.send('这是一个根路由!')
})

app.get('/router1', (req, res) => {
  res.send('这是一个router1路由!')
})
app.get('/router2', (req, res) => {
  res.send('这是一个router2路由!')
})


app.listen(3000, () => {
  console.log('app listening on port 3000!')
})
GET '/router2' //打印日志,并且返回结果

这就是一个简单的中间件解释了。大家也可以回去看看你原来写过的代码,是否对之前的use这个玩意有点启发了?

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
javascript 获取页面的高度及滚动条的位置的代码
May 06 Javascript
javascript下string.format函数补充
Aug 24 Javascript
js获取表格的行数和列数的方法
Oct 23 Javascript
理解javascript函数式编程中的闭包(closure)
Mar 08 Javascript
jQuery深拷贝Json对象简单示例
Jul 06 Javascript
利用HTML5+Socket.io实现摇一摇控制PC端歌曲切换
Jan 13 Javascript
微信小程序 首页制作简单实例
Apr 07 Javascript
webpack打包js文件及部署的实现方法
Dec 18 Javascript
JavaScript数组特性与实践应用深入详解
Dec 30 Javascript
小程序分页实践之编写可复用分页组件
Jul 18 Javascript
微信小程序实现音频文件播放进度的实例代码
Mar 02 Javascript
浅谈vue的第一个commit分析
Jun 08 Javascript
详解vue中this.$emit()的返回值是什么
Apr 07 #Javascript
浅谈javascript中的prototype和__proto__的理解
Apr 07 #Javascript
javascrit中undefined和null的区别详解
Apr 07 #Javascript
详解服务端预渲染之Nuxt(介绍篇)
Apr 07 #Javascript
vue设计一个倒计时秒杀的组件详解
Apr 06 #Javascript
js字符串处理之绝妙的代码
Apr 05 #Javascript
微信小程序自定义导航栏实例代码
Apr 05 #Javascript
You might like
php绘图之生成饼状图的方法
2015/01/24 PHP
优化WordPress的Google字体以加速国内服务器上的运行
2015/11/24 PHP
xtree.js 代码
2007/03/13 Javascript
javascript 写类方式之二
2009/07/05 Javascript
jquery中获取元素的几种方式小结
2011/07/05 Javascript
Javascript处理DOM元素事件实现代码
2012/05/23 Javascript
jQuery实现的仿百度分页足迹效果代码
2015/10/30 Javascript
基于jQuery实现页面搜索功能
2020/03/26 Javascript
JS判断是否在微信浏览器打开的简单实例(推荐)
2016/08/24 Javascript
原生JS实现《别踩白块》游戏(兼容IE)
2017/02/20 Javascript
vue-loader教程介绍
2017/06/14 Javascript
vue单页应用加百度统计代码(亲测有效)
2018/01/31 Javascript
JS实现的倒计时恢复按钮点击功能【可用于协议阅读倒计时】
2018/04/19 Javascript
微信小程序自定义组件封装及父子间组件传值的方法
2018/08/28 Javascript
JS前端知识点总结之页面加载事件,数组操作,DOM节点操作,循环和分支
2019/07/04 Javascript
layui button 按钮弹出提示窗口,确定才进行的方法
2019/09/06 Javascript
详解vue-router 动态路由下子页面多页共活的解决方案
2019/12/22 Javascript
js实现简单的贪吃蛇游戏
2020/04/23 Javascript
[56:01]2018DOTA2亚洲邀请赛 3.31 小组赛 B组 Effect vs EG
2018/03/31 DOTA
python中对list去重的多种方法
2014/09/18 Python
Python列表(list)常用操作方法小结
2015/02/02 Python
Python的Flask框架中集成CKeditor富文本编辑器的教程
2016/06/13 Python
python数据类型_字符串常用操作(详解)
2017/05/30 Python
widows下安装pycurl并利用pycurl请求https地址的方法
2018/10/15 Python
用Python画小女孩放风筝的示例
2019/11/23 Python
在python中logger setlevel没有生效的解决
2020/02/21 Python
python3 循环读取excel文件并写入json操作
2020/07/14 Python
python 图像增强算法实现详解
2021/01/24 Python
HTML5单选框、复选框、下拉菜单、文本域的实现代码
2020/12/01 HTML / CSS
介绍下Java中==和equals的区别
2013/09/01 面试题
境外导游求职信
2014/02/27 职场文书
简单的个人租房协议书范本
2014/11/26 职场文书
2015大学生入党个人自传
2015/06/26 职场文书
廉洁自律准则学习心得体会
2016/01/13 职场文书
2016学习全国教书育人楷模先进事迹心得体会
2016/01/21 职场文书
攻略丨滑雪究竟该选哪款对讲机?
2022/02/18 无线电