当前位置: 首页 > news >正文

node.js学习笔记:中间件

node.js学习笔记:中间件

      • 一、中间件的基本结构
      • 二、编写和使用中间件的步骤
        • 1. 编写中间件函数
        • 2. 注册中间件
        • 3. 错误处理中间件
      • 三、中间件的核心特性
      • 四、常见中间件类型
      • 总结

在 Node.js(尤其是 Express 框架)中,中间件(Middleware)是一个函数,它可以访问请求对象(req)、响应对象(res)以及应用程序的下一个中间件函数(next)。中间件的主要作用是:处理请求、修改请求/响应对象、终止请求-响应周期,或调用下一个中间件。

一、中间件的基本结构

一个标准的 Express 中间件函数包含 3 个参数:req(请求)、res(响应)、next(下一个中间件)。如果是错误处理中间件,则有 4 个参数:errreqresnext

基本格式:

// 普通中间件
const myMiddleware = (req, res, next) => {// 1. 处理逻辑(如日志、验证、修改req/res等)// 2. 调用 next() 交给下一个中间件;或用 res.send() 终止请求next(); // 必须调用,否则请求会被挂起
};// 错误处理中间件(多一个 err 参数)
const errorMiddleware = (err, req, res, next) => {// 处理错误res.status(500).send('服务器错误:' + err.message);
};

二、编写和使用中间件的步骤

以 Express 为例,编写中间件并应用到项目中,通常分为 3 步:

1. 编写中间件函数

根据需求实现具体逻辑,例如:

示例 1:日志中间件(记录请求信息)

// 记录请求的方法、URL、时间
const loggerMiddleware = (req, res, next) => {const { method, url } = req;const time = new Date().toLocaleString();console.log(`[${time}] ${method} ${url}`);next(); // 交给下一个中间件
};

示例 2:参数验证中间件(检查请求参数)

// 验证 POST 请求的 body 中是否包含 username
const validateUserMiddleware = (req, res, next) => {if (!req.body.username) {// 参数错误,直接响应,终止请求return res.status(400).send('缺少 username 参数');}next(); // 参数正确,继续下一步
};

示例 3:异步中间件(处理异步操作)

// 模拟异步查询数据库,检查用户是否存在
const checkUserExists = async (req, res, next) => {try {const userId = req.params.id;// 模拟数据库查询const user = await db.findUser(userId); // 假设 db.findUser 是异步函数if (!user) {return res.status(404).send('用户不存在');}// 将查询结果挂载到 req 上,供后续中间件使用req.user = user;next();} catch (err) {// 异步错误需传递给错误处理中间件next(err); // 调用 next(err) 会触发错误处理中间件}
};
2. 注册中间件

通过 app.use() 或路由方法(如 app.get())注册中间件,使其生效。

全局中间件(对所有请求生效):

const express = require('express');
const app = express();// 注册日志中间件(所有请求都会经过它)
app.use(loggerMiddleware);// 解析 JSON 请求体的内置中间件(Express 自带)
app.use(express.json());

局部中间件(仅对特定路由生效):

// 仅对 POST /user 生效的验证中间件
app.post('/user', validateUserMiddleware, (req, res) => {res.send(`创建用户:${req.body.username}`);
});// 对 /user/:id 路由生效的异步中间件
app.get('/user/:id', checkUserExists, (req, res) => {// 使用 checkUserExists 中间件挂载的 req.userres.send(`用户信息:${JSON.stringify(req.user)}`);
});

多个中间件串联

// 多个中间件按顺序执行
app.get('/profile',authMiddleware, // 先验证登录checkRoleMiddleware, // 再检查权限(req, res) => { // 最后处理响应res.send('用户资料');}
);
3. 错误处理中间件

专门处理请求过程中产生的错误(同步/异步错误),必须定义 4 个参数(err, req, res, next),否则 Express 会将其视为普通中间件。

// 注册错误处理中间件(通常放在所有路由之后)
app.use((err, req, res, next) => {console.error('错误详情:', err.stack);// 区分错误类型,返回不同状态码if (err.type === 'validation') {return res.status(400).send(err.message);}// 未知错误返回 500res.status(500).send('服务器内部错误');
});

触发错误处理中间件

  • 同步错误:直接 throw new Error('错误信息')
  • 异步错误:调用 next(err)(如示例 3 中的 next(err)

三、中间件的核心特性

  1. 执行顺序:按注册顺序执行,先注册的中间件先处理请求(类似流水线)。

    app.use((req, res, next) => {console.log('中间件 1');next();
    });
    app.use((req, res, next) => {console.log('中间件 2');next();
    });
    // 访问任何接口,会先打印 "中间件 1",再打印 "中间件 2"
    
  2. 终止请求:如果中间件中调用了 res.send()res.json() 等响应方法,请求-响应周期会终止,后续中间件不再执行。

    app.use((req, res, next) => {res.send('终止请求');next(); // 这行代码不会生效,因为响应已发送
    });
    app.use((req, res, next) => {console.log('不会执行');
    });
    
  3. 修改请求/响应对象:中间件可以给 reqres 添加属性/方法,供后续中间件或路由使用(如示例 3 中的 req.user)。

四、常见中间件类型

  • 应用级中间件:通过 app.use() 注册,对所有路由生效。
  • 路由级中间件:通过 router.use() 注册,仅对特定路由模块生效。
  • 内置中间件:Express 自带的中间件,如 express.json()(解析 JSON 请求体)、express.static()(托管静态资源)。
  • 第三方中间件:如 cors(处理跨域)、morgan(日志)、helmet(安全头),需通过 npm 安装后使用。

总结

编写中间件的核心是:

  1. 定义一个接收 req, res, next(或 err, req, res, next)的函数。
  2. 在函数中实现特定逻辑(日志、验证、异步操作等)。
  3. 调用 next() 传递控制权,或用 res.send() 终止请求。
  4. 通过 app.use() 或路由方法注册中间件,注意执行顺序。

中间件是 Express 的核心思想,掌握它可以灵活处理各种请求场景,提高代码复用性。


文章转载自:

http://FDvtBcn1.bnLch.cn
http://4t28qtC9.bnLch.cn
http://Vjh1nJXd.bnLch.cn
http://Ns7sLacV.bnLch.cn
http://Pd5hyFau.bnLch.cn
http://ae2xcQZ4.bnLch.cn
http://h6P0NpgH.bnLch.cn
http://FN7Iqho8.bnLch.cn
http://j0QtS07u.bnLch.cn
http://fWvgCrl9.bnLch.cn
http://M9MbZ6LP.bnLch.cn
http://YAG2xdT1.bnLch.cn
http://1yC4cLBi.bnLch.cn
http://LWyNwA5t.bnLch.cn
http://qGEMXJ7N.bnLch.cn
http://Sj0r5SQ1.bnLch.cn
http://UvIZlveB.bnLch.cn
http://8k06TdjY.bnLch.cn
http://ep6aV59g.bnLch.cn
http://uDJYCGs0.bnLch.cn
http://XHunrHzD.bnLch.cn
http://oDU1qzEY.bnLch.cn
http://rt76S4hn.bnLch.cn
http://ZwtZFP3i.bnLch.cn
http://QNxaSXfu.bnLch.cn
http://ZSLj1njb.bnLch.cn
http://YwbAZOoC.bnLch.cn
http://L6LkDIIn.bnLch.cn
http://4oMP4JVL.bnLch.cn
http://2LvRuL5P.bnLch.cn
http://www.dtcms.com/a/385857.html

相关文章:

  • Debian更新安全补丁常用命令
  • LeetCode:6.三数之和
  • 号称用rust重写的sqlite数据库tursodb与sqlite及duckdb性能比较
  • cuda stream
  • 云计算在云手机中的作用
  • C++STL学习:unordered_set/unordered_map
  • RTOS 任务状态与调度机制详解
  • 基于 Java EE+MySQL+Dart 实现多平台应用的音乐共享社区
  • 解密Tomcat的I/O模型:非阻塞之上,为何要兼容阻塞?
  • 时序数据库IoTDB如何支撑万亿级设备连接?
  • 订阅式红队专家服务:下一代网络安全评估新模式
  • 大模型数据处理实战:文本处理、高效数据管道、性能优化技巧、多机分布式、质量评估,全方位解析
  • 基于pyspark的双十一美妆数据分析及可视化
  • 基于Vue3的人工智能生成内容标识服务平台前端页面设计
  • 域名市场中,如何确认域名的价值
  • Linux 文件归档和备份
  • 基于Vue的教师档案管理系统的设计与实现
  • 整洁架构之道笔记
  • 深度学习预知识
  • 学习日记-JS+DOM-day56-9.16
  • 51单片机LED闪烁编程实战
  • 字符数组与字符串
  • ⸢ 肆-Ⅱ⸥ ⤳ 风险发现体系的演进(上):背景与现状
  • [js解密分析]方仔照相馆:用3D电子说明书重塑定制积木体验
  • 【Vue3 ✨】Vue3 入门之旅 · 第一篇:Vue3 简介与新特性概览
  • docker 容器中导出pg数据库
  • 【软考】笔记总结一
  • 云望无人机图传16公里原理:云端成像的新纪元,远距离传输不再难
  • OpenHarmony包管理子系统核心源码深度解读:从BundleManager到AMS,彻底打通应用安装、卸载与沙箱机制全链路
  • 10套政务类BI可视化大屏案例:原型设计思路拆解