Express的使用笔记3 中间件

news/2024/10/12 16:18:04





日志中间件

// 挂载会每个接口都执行这段代码
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'))

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ryyt.cn/news/70709.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

2024 Navicat Premium 16+17安装教程(附激活方法)

Navicat Premium,作为一款功能全面的集成数据库管理工具,无缝支持多样化的数据库类型,为用户带来前所未有的高效与便捷管理体验。它不仅涵盖了连接管理、数据导入导出、同步迁移、备份恢复等核心功能,确保用户能够游刃有余地应对各类数据库管理挑战,还进一步拓展了数据库对…

gost socks5代理

购买云主机开放所有tcp端口 配置云主机 https://mirrors.tuna.tsinghua.edu.cn/elrepo/kernel/el8/x86_64/ 选择清华镜像源[root@iZbp141m9g3iwgwsmh7pvzZ yum.repos.d]# cat >> /etc/yum.repos.d/elrepo.repo << q [elrepo] name=elrepo gpgcheck=0 baseurl=https…

2024-2025-1 20241403 《计算机基础与程序设计》第三周学习总结

学期(2024-2025-1) 学号(20241403) 《计算机基础与程序设计》第三周学习总结 作业信息这个作业属于哪个课程 <班级的链接>(如2024-2025-1-计算机基础与程序设计)这个作业要求在哪里 <作业要求的链接>(如2024-2025-1计算机基础与程序设计第三周作业)这个作业的…

基于FIFO使用UART实现FPGA板与PC通信

基于FIFO使用UART实现FPGA板与PC通信 1. UART 简介 UART(通用异步收发传输器)是一种常用的串行通信协议,广泛用于FPGA与外部设备(如PC、传感器等)之间的通信。UART 通信的核心是将并行数据转换为串行数据传输,然后在接收端再将串行数据恢复为并行数据。 UART协议特点:异…

软件构造,生成算式采用CSV、XML、JSON三种形式进行存储并读取。

编写代码完成将生成的算式及习题长期保存下来,采用CSV、XML、JSON三种形式进行存储并读取。提交相关代码及运行截图。import random import csv import json import xml.etree.ElementTree as ET from xml.dom import minidom# 生成随机算式数据 def generate_exercises(count…

一文详述:AI 网关与 API 网关到底有什么区别?

近年来AI 发展火热,大模型已经成为推动各行各业业务创新和增长的关键力量。随之而来问题是“企业该如何安全管理和部署AI应用的挑战?”AI基础架构的设计不仅要支持现有的业务需求,还要能够适应未来技术的快速发展。在这样的背景下,AI网关的概念应运而生,AI 网关在AI应用的…

Armitage:MSF图形界面神器

原创 自然嗨 嗨嗨安全免责声明 请勿利用文章内的相关技术从事非法测试,如因此产生的一切不良后果与文章作者无关。Armitage Armitage是一款Java写的Metasploit图形界面化的攻击软件,可以用它结合 Metasploit中已知的exploit来针对主机存在的漏洞自动化攻击。通过命令行的方式…