node.js之中间件

294 阅读4分钟

前言

中间件是Express框架中很重要,很核心的一部分。上一篇文章我们主要介绍了Express中的路由,而且一个Express应用就是在调用各种中间件。除了路由之外,Express还有一个核心内容就是中间件。我们这篇文章主要介绍中间件的作用和用法。

中间件

中间件本质上就是一个回调函数,它可以访问请求对象(req),响应对象(res)和next变量。

中间件的作用

中间件最核心的作用就是使用函数封装公共逻辑,简化代码。除此之外,中间件还具有以下功能。

  • 执行任何代码
  • 修改请求和响应对象(req, res)
  • 终结请求-响应循环(res.end)
  • 调用堆栈中的下一个中间件(next)

需要注意的是:如果当前中间件没有终结请求-响应循环,则必须调用next()方法将控制权交给下一个中间件。

中间件的类型

中间件有很多类型,一般可以分为以下几类:

  1. 应用级中间件
  2. 路由级中间件
  3. 错误处理中间件
  4. 内置中间件
  5. 第三方中间件

1. 应用级中间件

应用级中间件绑定到 app 对象 使用 app.use() 和 app.METHOD(),因此也叫全局中间件。 其中, METHOD 是需要处理的 HTTP 请求的方法,例如 GET, PUT, POST 等等,全部小写。

声明中间件

定义中间件的方法如下:

let recordMiddleWare = (req, res, next) => {
  // 实现具体功能
  console.log('这是一个中间件');
  // 执行next函数(当如果希望执行完中间件函数之后,仍然继续执行路由中的回调函数,必须调用nextnext();
}

应用中间件

const express = require('express');
const app = express();
app.use(recordMiddleWare);

当然上述代码也可以写成这样:

app.use((req, res, next) => {
  // 实现具体功能
  console.log('这是一个中间件');
  // 执行next函数(当如果希望执行完中间件函数之后,仍然继续执行路由中的回调函数,必须调用nextnext();
})
const express = require('express');
const app = express();

// 应用级组件(后面的路由都会执行这个中间件)
app.use((req, res, next) => {
  // 验证token是否过期
  let isValid = true;
  if (isValid) {
    next()
  } else {
    res.end('error');
  }
});

2. 路由级中间件

很明显,路由级中间件是和全局中间件是不一样的,它更相当于是一个局部中间件,只有在特定路由下才能执行的中间件。路由级中间件是由app.route创建的,而且可以链式调用

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

app.route('/test')
.get((req, res) => {
  res.send('get ok!')
})
.post((req, res) => {
  res.send('post ok!')
});

也可以使用express的router类创建路由组件,一个Router实例是一个完整的中间件和路由系统,这种方式下可以导出给其他模板使用。

const app = express();
const router = express.Router();

// 没有挂载路径的中间件,通过该路由的每个请求都会执行该中间件
router.use(function (req, res, next) {
  console.log('Time:', Date.now())
  next()
})

// 一个中间件栈,显示任何指向 /user/:id 的 HTTP 请求的信息
router.use('/user/:id', function(req, res, next) {
  console.log('Request URL:', req.originalUrl)
  next()
}, function (req, res, next) {
  console.log('Request Type:', req.method)
  next()
})

还可以使用router.route()方法创建路由组件,接受访问路径作为参数,这种方式下可以导出给其他模板使用。

const app = express();
const router = express.Router();
router.route('/test')
.get((req, res) => {
  res.send('get ok!')
})
.post((req, res) => {
  res.send('post ok!')
});

3.错误处理组件

错误处理组件就是用来处理错误逻辑的,接收四个参数,多了一个err.

const app = express();
app.use((err, req, res, next) => {
  console.log('ERR', err)
  res.send('err')
})

4. 内置的中间件

上面的中间件是我们自己定义的中间件,Express有自己的内置的中间件。也是唯一的内置中间件,那就是serve-static,主要是负责托管静态资源的。

//引入express框架
const express = require('express');
//创建服务对象
const app = express();
//静态资源中间件的设置,将当前文件夹下的public目录作为网站的根目录
app.use(express.static('./public')); //当然这个目录中都是一些静态资源
//如果访问的内容经常变化,还是需要设置路由
//但是,在这里有一个问题,如果public目录下有index.html文件,单独也有index.html的路由
//则谁书写在前,优先执行谁
app.get('/index.html',(request,response)=>{
	respsonse.send('首页');
});
//监听端口
app.listen(3000,()=>{
	console.log('3000 端口启动....');
});

需要注意以下几点:

  1. index.html 文件为默认打开的资源
  2. 如果静态资源与路由规则同时匹配,谁先匹配谁就响应
  3. 路由响应动态资源,静态资源中间件响应静态资源

5. 第三方中间件

网上有很多第三方中间件,我们可以下载这些第三方中间件来帮助处理我们的一些逻辑。比如 cookie-parser,它可以用于解析cookie。

第三方中间件的用法如下:

首先安装第三方组件

npm i cookie-parser

然后就可以使用第三方中间件了

const express = require('express')
const app = express()
const cookieParser = require('cookie-parser')

// 加载用于解析 cookie 的中间件
app.use(cookieParser())