中间件

中间件

  • 内置中间件:
    • app.use(express.urlencoded({ extended: false })); 处理POST请求的
    • app.use(express.static('./webapp')); 当前app.js同目录下webapp文件夹作为静态资源访问
  • 第三方中间件:比如multer、express-jwt、express-session、....【实际开发中,自己写中间件的机会并不大,一般都有对应的第三方中间件。】

介绍

  • 中间件(Middleware ),特指业务流程的中间处理环节。

  • 中间件,是express最大的特色,也是最重要的一个设计

  • 很多第三方模块,都可以当做express的中间件,配合express,开发更简单。

  • 一个express应用,是由各种各样的中间件组合完成的

  • 为了理解中间件,我们先来看一下我们现实生活中的自来水厂的净水流程:

    • 自来水厂从获取水源到净化处理交给用户,中间经历了一系列的处理环节
    • 我们称其中的每一个处理环节就是一个中间件
    • 这样做的目的既提高了生产效率也保证了可维护性。

中间件,本质上就是一个函数;中间件函数中有四个基本参数, err、req、res、next

  • err:如果带有err参数,并且中间件函数给了全部的4个参数,那么这个中间件有特殊的用法,表示错误处理中间件,错误处理中间件,可以处理前面所有的中间件抛出的错误。
    • req:请求相关的对象
    • res:响应相关的对象
    • next:它是一个函数,某些时候,可以省略

next()

  • 无参数:执行完当前中间件,往下一个匹配到中间件函数执行,直到遇见res.send();

    const express = require("express");
    const app = express();
    app.listen(3000, () => console.log("启动成功, http://localhost:3000"));
    
    // 定义中间件函数 - 函数体
    // 给服务器注册全局生效的中间件 app.use();无论是get 还是post请求都会经过这个中间件处理
    app.use(function(req, res, next){
        console.log("我是一个中间件函数, 我处理完了1");
        
        // 调用next函数, 才会传递给下一个函数处理(按照编写顺序)
        next(); 
    });
    app.use(function(req, res, next){
        console.log("我是一个中间件函数, 我处理完了2");
        next();
    });
    
    // 路由 - 处理完毕 - 返回响应数据
    app.get("/api/list", (req, res) => {
        res.send("get请求 /api/list");
    })
    
    app.get("/api/book", (req, res) => {
        res.send("get请求 /api/book");
    })
    
  • 应用: 所有的接口,加快给用户返回服务器的系统时间

  • 曾经:接口多了就显得很肉;

    var momentObj = require('moment');
    app.get("/api/getbook", (req, res) => {
        let nowDate = momentObj.format("YYYY-MM-DD HH:mm:ss");
        res.send({
            msg: "get方式/api/getbooks被访问了",
            time: nowDate
        })
    })
    
    app.post("/api/addbook", (req, res) => {
        let nowDate = momentObj.format("YYYY-MM-DD HH:mm:ss");
        res.send({
            msg: "post方式/api/addbook",
            time: nowDate
        })
    })
    
  • 中间件设计:

    // 可以提到公共的中间件里来写 - 因为所有的中间件都共享同一个req和 res对象
    app.use((req, res, next) => {
        res.nowDate = momentObj.format("YYYY-MM-DD HH:mm:ss");
        // new Date() 获取的是标准时间, 比北京时间少8小时
        next();
    })
    
    app.get("/api/getbook", (req, res) => {
        res.send({
            msg: "get方式/api/getbooks被访问了",
            time: res.nowDate
        })
    })
    
    app.post("/api/addbook", (req, res) => {
        res.send({
            msg: "post方式/api/addbook",
            time: res.nowDate
        })
    })
    

next(?)

  • 给next传递参数:表示发生了错误;将会越过后续所有的中间件,直接进入最后的错误处理中间件;

    // 自定义中间件
    app.use((req, res, next) => {
      next('发生错误了');
    });
    
    app.get('/get/books', (req, res, next) => {
      res.send("给前端 书籍的 数据");
    });
    app.get('/get/sts', (req, res, next) => {
      res.send("给前端 学生的 数据");
    });
    
    // 最后 用于错误处理中间件
    app.use((err, req, res, next) => {
      res.send({ status: 500, message: err })
    });
    
    // 自定义中间件
    app.use((req, res, next) => {
      //  如果没有数据
      if (req.query.token == "") {
        next("没有token的错误");
      }
      // 
      else {
        next();
      }
    });
    
    app.get('/get/sts', (req, res, next) => {
      res.send("给前端 学生的 数据");
    });
    app.get('/get/books', (req, res, next) => {
      res.send("给前端 图书的 数据");
    });
    
    app.use((err, req, res, next) => {
      res.send({ status: 500, message: err })
    });     // err 为next中的值
    

其他用法

```
// app.use 中的中间件,可以处理所有的GET请求和所有的POST请求,没有指定路径,那么处理所有接口
app.use(中间件函数);
app.use(中间件函数, 中间件函数, 中间件函数 .....);

// 下面的中间件函数,只处理 /api 开头的接口
app.use('/api', 中间件函数);


// 下面的中间件(了解),只为当前接口 /my/userinfo 这个接口服务
app.get('/my/userinfo', 中间件函数);
app.get('/my/userinfo', 中间件函数, 中间件函数, 中间件函数, 中间件函数 .....);

// 下面的几个中间件,是处理 /api/login 接口的
app.post('/api/login', 中间件函数)
app.post('/api/login', 中间件函数, 中间件函数, 中间件函数, 中间件函数 .....);
```
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值