第五部分:第五节 - Express 路由与中间件进阶:厨房的分工与异常处理

发布于:2025-05-17 ⋅ 阅读:(12) ⋅ 点赞:(0)

随着你的 Express 应用变得越来越大,所有的路由和中间件都写在一个文件里会变得难以管理。这时候就需要将代码进行拆分和组织。此外,一个健壮的后端应用必须能够优雅地处理错误和一些常见的 Web 开发问题,比如跨域。

路由模块化 (express.Router):

express.Router 是 Express 提供的一个迷你应用,它有自己的中间件和路由。你可以把处理某个特定资源的路由(比如所有用户相关的路由)放到一个单独的文件中,然后像中间件一样将其挂载到主应用上。这就像在厨房里为不同的菜品(资源)设立了专门的操作台(路由文件),每个操作台有自己的工作流程,但它们最终都属于整个厨房(主应用)。

创建一个新的文件,比如 routes/users.js

// routes/users.js
const express = require('express');
const router = express.Router(); // 创建一个 Router 实例

// 这里可以定义用户相关的中间件,只应用于本路由文件中的路由
// router.use((req, res, next) => { console.log('用户路由中间件'); next(); });

// 定义用户相关的路由
router.get('/', (req, res) => {
  // 处理获取所有用户的逻辑
  res.send('获取所有用户');
});

router.get('/:userId', (req, res) => {
  const userId = req.params.userId;
  // 处理获取单个用户的逻辑
  res.send(`获取用户 ID: ${userId}`);
});

router.post('/', (req, res) => {
  // 处理创建用户的逻辑
  res.send('创建新用户');
});

// ... 其他用户相关的路由 (PUT, DELETE)

module.exports = router; // 导出 router 实例 (CommonJS 方式)

// 如果使用 ES Modules:
// export default router;

在你的主应用文件 app.js 中导入并使用这个路由模块:

// app.js
const express = require('express');
const app = express();
const port = 3000;

// 导入用户路由模块
const usersRouter = require('./routes/users');
// const usersRouter from './routes/users.js'; // ES Modules

// ... 其他中间件 (如 body-parser)

// 将用户路由模块挂载到 /api/users 路径下
app.use('/api/users', usersRouter);

// ... 其他路由和中间件

// 启动服务器
app.listen(port, () => {
  console.log(`应用运行在 http://localhost:${port}`);
});

// 现在访问 /api/users 会由 usersRouter 处理
// 访问 /api/users/123 会由 usersRouter.get('/:userId', ...) 处理

错误处理中间件:

在 Express 中,错误处理中间件有四个参数:(err, req, res, next)。当你在任何路由或普通中间件中调用 next(err) 并传入一个错误对象时,Express 会跳过后续的路由和中间件,直接进入错误处理中间件。这就像厨房里某个环节出了问题(比如菜烧焦了),不用继续整个流程,直接通知服务员(调用错误处理中间件)去处理这个“异常订单”。

通常,你会在所有路由和普通中间件的后面定义错误处理中间件,以捕获所有未被处理的错误。

// app.js (接着上面的代码)

// ... 所有路由和普通中间件 ...

// 404 错误处理 (放在所有有效路由之后)
app.use((req, res, next) => {
    res.status(404).send("对不起,找不到该页面!");
});

// 错误处理中间件 (四个参数)
app.use((err, req, res, next) => {
  console.error("服务器端错误:", err.stack); // 打印错误堆栈到服务器控制台
  res.status(500).send("服务器内部出错!"); // 向客户端发送 500 状态码和错误信息
});

// 在路由中模拟错误
app.get('/error-test', (req, res, next) => {
  // 模拟一个错误
  const myError = new Error("这是一个测试错误");
  next(myError); // 将错误传递给错误处理中间件
});

常用的第三方中间件:

Express 的生态系统非常丰富,有很多优秀的第三方中间件可以方便地集成。

  • morgan (日志记录): 记录所有收到的 HTTP 请求信息,对于调试和监控非常有帮助。就像餐厅里的订单记录系统。
    • 安装: npm install morgan
    • 使用: const morgan = require('morgan'); app.use(morgan('dev')); (dev 是预设的日志格式)
  • cors (跨域资源共享): 处理浏览器的同源策略限制,允许来自不同域的前端应用访问你的后端 API。这就像允许来自不同地区的顾客在你的餐厅点餐。
    • 安装: npm install cors
    • 使用: const cors = require('cors'); app.use(cors()); (允许所有跨域请求,也可以配置更精细的规则)
// app.js (接着上面的代码)

const morgan = require('morgan');
const cors = require('cors');

// 使用 morgan 中间件记录日志
app.use(morgan('dev'));

// 使用 cors 中间件处理跨域
app.use(cors());

// ... 其他路由和中间件 ...

小例子:模块化路由和全局错误处理

请参考上面关于 express.Router 和错误处理中间件的代码示例,将它们集成到一个完整的 Express 应用中。

小结: 使用 express.Router 可以将复杂的路由逻辑拆分到单独的文件中,提高代码的可组织性。错误处理中间件是捕获和处理应用错误的统一方式。morgancors 是两个非常常用的第三方中间件,分别用于日志记录和跨域处理。

练习:

  1. 在你的 Express 项目中,为之前的“书籍”资源创建一个单独的路由文件 (routes/books.js)。
  2. routes/books.js 中,使用 express.Router() 定义至少两个路由(例如 GET / 和 GET /:bookId)。
  3. 在主应用文件 app.js 中导入 routes/books.js 并将其挂载到 /api/books 路径下。
  4. 在主应用中添加一个 404 错误处理中间件(放在所有有效路由之后)。
  5. 在主应用中添加一个全局错误处理中间件,当接收到错误时,记录错误到控制台并向客户端发送 500 状态码。
  6. 安装并使用 morgan 中间件记录所有请求日志。
  7. 安装并使用 cors 中间件,允许所有来源的跨域请求。

网站公告

今日签到

点亮在社区的每一天
去签到