node.js 22 默认严格处理未捕获的 promise 拒绝,mongodb 驱动所有异步操作(如 connect、findone)若未用 await/try-catch 或 .catch() 显式处理,将直接终止进程;须配置 serverselectiontimeoutms 并确保每个 promise 有错误处理终点。

Node.js 22 默认启用 unhandledRejection 严格模式,任何未被 .catch() 或 try/catch 捕获的 Promise 拒绝都会直接触发进程退出——MongoDB 驱动的连接、查询等异步操作一旦失败,又没显式处理,就必然报 UnhandledPromiseRejectionWarning 甚至中止进程。
connect() 调用后没 await 就丢弃 Promise
这是最常见原因:调用 client.connect() 后没 await,也没接 .catch(),导致拒绝被忽略。
- 错误写法:
client.connect(); // Promise 被创建但无人监听 - 正确做法必须包裹在 async 函数中并
await,或链式加.catch() - 若在模块顶层(非函数内)调用,需用
(async () => { await client.connect(); })();包裹 - Node.js 22 不再容忍“放任自流”的 Promise,哪怕只是开发时漏写,也会立即报错
错误处理只覆盖部分路径,漏掉 .then() 分支中的 reject
.then() 的第二个参数(onRejected)和 .catch() 并不等价:前者只捕获前一个 Promise 的 reject,后者能捕获链中任意环节的 reject —— 但很多人只写 .then(success),完全没加错误分支。
- 错误示例:
client.connect().then(() => console.log('ok'));→ 连接失败时无响应,触发 unhandled rejection - 推荐统一用
.catch()结尾:client.connect().then(...).catch(console.error) - 更稳妥的是用
try/catch+await,它能捕获同步 throw 和 Promise reject 两种错误 - 注意:
catch必须是链的最后一个环节,中间任何.then()若抛出新错误且没后续catch,仍会漏掉
MongoDB 连接选项缺失导致静默超时,最终触发 unhandledRejection
Node.js 22 下,驱动默认行为更“激进”:如果连接过程卡在 DNS 解析、网络不通或服务未启动,connect() 会在几秒后自动 reject,但若你没设 serverSelectionTimeoutMS,实际超时可能长达 30 秒以上,期间 Promise 一直悬空,最终被判定为 unhandled。
- 务必显式配置超时:
new MongoClient(url, { serverSelectionTimeoutMS: 5000 }) -
useUnifiedTopology: true已是 v4+ 默认值,但显式写出可避免旧代码迁移遗漏 - 不要依赖
process.on('unhandledRejection', ...)做兜底——Node.js 22 中这属于降级兼容,不能阻止进程退出 - 验证 MongoDB 服务是否真在运行:
mongosh --eval "db.runCommand({ping:1})",否则连超时都等不到,直接被底层 socket error 拒绝
真正容易被忽略的点是:Node.js 22 把“未处理 Promise 拒绝”从警告升级为默认终止行为,而 MongoDB 驱动绝大多数 API(connect、db.collection().findOne()、insertOne())全返回 Promise —— 意味着**只要有一个异步调用漏了错误处理,整个服务就不可靠**。别指望开发时 console 一下就完事,得让每个 Promise 都有明确的终点。











