Express的使用笔记3 中间件





日志中间件

// 挂载会每个接口都执行这段代码
app.use((req,res,next)=>{
    console.log(req.method,req.url,Date.now())
    next() //下一个中间件
})

2.中间件的顺序很重要
如果有一个普通接口写在上面代码之前,那么就不会进入上面的函数中
但是如果在接口中第二个回调函数的参数中加入next,则可以进入

// 不会打印时间戳及相关信息
app.get("/todos", async (req, res) => {
  try {
    const db = await getDB();
    res.status(200).json(db.todos);
  } catch (err) {
    return res.status(500).json({ error: err.message });
  }
});
// 可以打印了~
app.get("/todos", async (req, res, next) => {
  try {
    const db = await getDB();
    res.status(200).json(db.todos);
    next()
  } catch (err) {
    return res.status(500).json({ error: err.message });
  }
});

我是讲武德的,这些课件截图源于b站up主小打小闹Studio
https://space.bilibili.com/13625996


在中间件函数中可以执行以下任何任务:
1).执行任何代码
2).修改request或response响应对象
3).结束请求响应周期
4).调用下一个中间件
如果当前的中间件功能没有结束请求-响应周期,则必须使用next()将控制权传递给下一个中间件功能。否则,该请求将被挂起。

2.Express中间件分类:
1)应用程序级别中间件 express实例.xxx
2)路由级别中间件 express.Router()
3)错误处理中间件 和其他中间件函数一样,但是四个参数
4)内置中间件
5)第三方中间件

1)通过Express实例挂载的中间件
a)不做任何限定的中间件

app.use((req, res, next) => {
  console.log(req.method, req.url, Date.now());
  next(); //下一个中间件
});

b)限定请求方法+请求路径的中间件
就是符合条件的APi被调用后才会进入这个中间件

//限定请求路径
app.use('/task',(req, res, next) => {
  console.log(req.method, req.url, Date.now());
  next(); //下一个中间件
});

app.get('/task',(req, res, next) => {
 res.status(200).send('是否会进入?')
})
//----页面进入/task中间件去打印方法和时间戳也会有‘是否进入’

//限定请求路径
app.use('/aaa',(req, res, next) => {
  console.log(req.method, req.url, Date.now());
  next(); //下一个中间件
});
//---这种就是不会进入打印了,因为匹配不上了

c)多个处理函数

app.use(
  "/",
  (req, res, next) => {
    console.log(req.method, req.url, Date.now());
    next();
  },
  (req, res, next) => {
    console.log('也会进来吗');
    // next();  //如果注释掉就不会进入下面的接口了
  }
);

app.get("/", (req, res, next) => {
  res.status(200).send("是否会进入?");
});

d)next('route') 下一步进入请求,而不是普通下一步

app.get(
  "/user/:id",
  function (req, res, next) {
    console.log(req.method, req.url, Date.now());
    console.log(typeof(req.params.id),'999')
    if (req.params.id === '2') {
      next("route"); //跳过也会进来吗函数的执行,直接进入是否会进入
    } else {
      next(); //继续往下执行
    }
  },
  function (req, res, next) {
    console.log("也会进来吗");
    next();
  }
);

app.get("/user/:id", (req, res, next) => {
  res.status(200).send("是否会进入?");
});

2)路由级别中间件
每个请求都需要app.xxx太过于繁琐 ,可以使用路由实例 相当于mini express 实例
后续就通过router.xxx()
a)根目录下创建一个router.js 文件,创建一个router实例

const express = require('express')
const router = express.Router()

b)配置路由

router.get('/',(req,res,next)=>{})

c) 导出路由实例

module.exports = router

d)将路由集成/挂载到Express实例应用中

const router = require('./router);
app.use(router)
//app.use('/abc',router) //在所有的路由前面都叫上限定访问的前缀

//可以将在app.js中写的所有路由配置放到router.js去

3)错误处理中间件
与其他中间件函数相同的方式定义错误处理中间件函数,除了使用四个参数而不是三个参数,一定是四个参数
一般在所有的中间件之后挂载错误处理函数中间

app.use((err,req,res,next)=>{
  console.log(err.stack)
  res.status(500).json({error:err.message})
})

在try catch中的catch里面使用next(err),传递错误的信息,跳过所有剩余的非错误处理路由和中间件函数,其实就是报错之后去触发错误处理函数,然后就结束任务
在router.js中将前面的所有路由中间件的catch里面都修改成next(err)

router.post("/todos", async (req, res,next) => {
  try {
    const db = await getDB();
    const reqBd = req.body;
    if (!reqBd.title) {
      return res.status(422).send({ error: "The field title is required" });
    }
    const lastTodoItem = db.todos[db.todos.length - 1];
    db.todos.push({
      id: lastTodoItem ? lastTodoItem.id + 1 : 1,
      title: reqBd.title,
    });
    await saveDB(db);
    res.status(200).send("添加成功!");
  } catch (err) {
    next(err);
  }
});

模拟一下报错的场景,正常可以响应500与对应的错误信息

通常我们会在最后的位置放置一个404的处理中间件函数,其实出现404的时候也有一个默认的html提示样式界面
404 与500类型的中间件没有先后的影响,会对应触发,但是其余会依此从上往下执行

app.use((req,res,next)=>{
  res.status(404).send('404 not found)
})

4)内置中间件
express.json() ---application/json
express.urlencoded() ---application/x-www-form-urlcoded
express.raw() ---application/octet-stream
express.text() ---text/plain
express.static() ---托管静态资源文件
5)第三方中间件
为了极简灵活的特性,epxress4之后将很多的中间件进行独立 ----middleware module
看文档使用即可
https://expressjs.com/zh-cn/resources/middleware.html

demo使用这些第三方中间件~~ 日志输出中间件
a)装包 npm install morgan
b)引入 var morgan = require('morgan')
c)挂载 app.use(morgan('tiny'))

posted @   JocelynFung  阅读(74)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
历史上的今天:
2021-10-12 threejs sprite 制作标签
Live2D 看板娘 / Demo
点击右上角即可分享
微信分享提示