立即修复您的 Express 错误处理

2025-06-10

立即修复您的 Express 错误处理

Express 可能是 Node.js 世界中最具影响力的软件包之一。它为我们提供了极其易于使用的 REST API 构建接口。它如此受欢迎,以至于任何可以放入中间件的东西,可能都已经有一个为 Express 而生的了。比如 pino、jwt、validator、fileupload、basic-auth、http-proxy 等等。难怪人们喜欢使用它。

承诺、异步、等待

Promises 现在是异步操作的标准,特别是因为我们还获得了异步函数和 await 关键字,这完全消除了对回调的需要,从而避免了所谓的回调地狱。

现在你会认为世界上最受欢迎的软件包之一应该可以与它们兼容,对吗?其实并非如此。

Express 最初开发时,Promise 还未真正成为标准,所以大家都在使用回调。虽然 JS 世界已经发展,但仍然有很多基于回调的 API,尤其是在 Node 本身中,例如fs模块。幸运的是,它有一个版本也支持 Promise API,或者我们可以使用一个名为promisify的工具。

快递有点糟糕

Express 的开发并不活跃,这可以理解——说到底,它的设计初衷就是要保持开放和极简主义。既然已经很棒了,何必费心去改变呢?

只不过 Express 的第 5 版实际上已经“开发”中了。这个版本已经持续了7 年多了——2014 年发布了 5.0.0-alpha1,它确实改进了一些地方,包括这个主要问题——Promises的错误处理

是的,如果您阅读错误处理的文档,您就会了解到承诺的错误处理不是由 Express 完成的 - 除非您正在运行 Express 5,否则您必须自己完成。

那么,当你忽略文档时会发生什么?你会遇到 Node.js 中最严重的异常——未处理的 Promise 拒绝,如果你使用的是较新的 Node.js,默认情况下会导致进程崩溃。你的 Express 错误处理程序肯定不会被调用,甚至响应也不会发送到客户端,所以你甚至不会看到 500 内部服务器错误。只是超时而已。

如何不处理异步错误的示例:



const express = require("express");

const app = express();

app.get("/boom", (req, res) => {
  throw "This will be handled";
});

app.get("/boomasync", async (req, res) => {
  throw "This will not be handled";
});

app.use((err, req, res, next) => {
  if (res.headersSent) {
    return next(err);
  }
  console.error(err);
  res.status(500).send("Oh no!");
});

app.listen(3000, () => console.log("Listening on 3000!"));


Enter fullscreen mode Exit fullscreen mode

有趣的是,很长一段时间以来,我相信 Node.js 14 仍然是这样,未处理的 Promise 拒绝只会在控制台中生成丑陋的日志。这个默认设置很长时间没有改变,因为人们担心它不太方便用户使用。我鼓励你查看PR发表相关帖子。

GitHub 评论:触发 BSOD 来教育用户

一个极其邪恶的想法😈

使固定

有很多方法可以解决这个问题。你可以直接.catch在每个处理程序后面加上。你可以使用 Express 5(alpha 版本)。你可以使用自定义路由器或中间件来处理这个问题。你可以使用一些神奇的修补包,比如express-async-errors。你也可以不使用 Express。

所有这些都有一些权衡,但我很乐意在现有代码库中修补 Express 的内部机制。对于新项目,我宁愿使用比 Express 更好的工具。

TypeScript

我对 Express 的另一个问题是它的 TypeScript 支持。它的定义假设 Request 对象始终相同,但实际情况完全不同。添加新字段req是依赖注入的常用方法。看一下pino 如何与 Express 集成。它添加了一个req.log可以在处理程序中使用的对象。然而,由于定义是常量,当你尝试使用它时,TypeScript 会对你的代码发出警告。

当然,您可以始终自己声明类型,也可以使用模块扩充,但这不是 da wae。

最后的话

Express 有很多替代方案——Koa、Hapi、Fastify、Hono、Nest.js 只是其中的几个例子。我个人比较喜欢 Koa。从表面上看,它与 Express 非常相似,只是做了一些细微的修改,但生态系统规模要小得多。绝对值得一试。

我发现很多高级开发人员都不知道这个问题,所以一定要问问你的同事,这可能是一个有趣的面试问题。我甚至觉得这么晚才发帖有点蠢。

编码愉快!

鏂囩珷鏉ユ簮锛�https://dev.to/pr0gramista/fix-your-express-error-handling-now-4h2l
PREV
项目5:Flex-gallery
NEXT
使用 CSS 滤镜实现穷人的黑暗模式