express.js框架中间件(middleware)

express.js框架中间件(middleware)

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

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

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

clipboard.png

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

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

中间件功能能够执行如下任务:bash

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

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

clipboard.png

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

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

有点乱?不要紧咱们看图koa

clipboard.png

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

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这个玩意有点启发了?

我是小龙,但愿对你们有所帮助

相关文章
相关标签/搜索