Mongoose抛出错误致程序崩溃,错误处理无效求助
环境信息
- Mongoose版本:6.3.4
- Node.js版本:18.6.0
- MongoDB版本:4.4
- 操作系统:Linux
- 操作系统版本:20.04
问题描述
Mongoose抛出错误时会导致程序直接退出崩溃。已经添加了基础错误处理,但程序仍会崩溃,推测存在未捕获的错误但无法定位具体位置。
数据库模块代码
import { Console } from 'console' import mongoose from 'mongoose' import Logger from '../util/logger' const logger = new Logger(`Worker/${process.pid}/database/site`) const schemas = { sitemeta: new mongoose.Schema({ setting: { type: String }, data: { type: Object } }, { collection: 'site-meta' }), project: new mongoose.Schema({ project_name: { type: String }, description: { type: String }, project_short_name: { type: String }, side_project: { type: Boolean }, project_body: { type: String }, thumbnail_source: { type: String } }, { collection: 'projects' }), admin: new mongoose.Schema({ key_hash: { type: String }, key_identifier: { type: String } }, { collection: 'admins' }) } async function dbConnect () { try { await mongoose.connect(process.env.MONGODB!, { dbName: 'site' }) mongoose.connection .on('error', () => logger.error('db error occured')) .once('open', () => logger.log('Connected to database')) } catch { logger.error('DB connect fail') } } dbConnect() const SiteMeta = mongoose.model('site-meta', schemas.sitemeta) const Project = mongoose.model('projects', schemas.project) const Admin = mongoose.model('admins', schemas.admin) export { SiteMeta, Project, Admin }
测试场景与错误日志
关闭MongoDB实例后启动应用,控制台先输出DB connect fail(说明catch块已触发),但随后程序仍崩溃,完整日志如下:
[ERROR] [08/08/2022, 03:46:14][wonik-website-core/Worker/8955/database/site] DB connect fail /home/myusr/website-core/node_modules/mongodb/src/sdam/topology.ts:606 const timeoutError = new MongoServerSelectionError( ^ MongoServerSelectionError: connect ECONNREFUSED MYIP:PORT at Timeout._onTimeout (/home/myusr/website-core/node_modules/mongodb/src/sdam/topology.ts:606:30) at listOnTimeout (node:internal/timers:564:17) at processTimers (node:internal/timers:507:7) { reason: TopologyDescription { type: 'Unknown', servers: Map(1) { 'wonik-server.ddns.net:4823' => [ServerDescription] }, stale: false, compatible: true, heartbeatFrequencyMS: 10000, localThresholdMS: 15, logicalSessionTimeoutMinutes: undefined }, code: undefined, [Symbol(errorLabels)]: Set(0) {} } [nodemon] app crashed - waiting for file changes before starting...
解决方案
问题根源是:mongoose.connect的try/catch仅能捕获初始连接阶段的同步/立即错误,而底层MongoDB驱动在后续拓扑检测时的异步错误会以未处理Promise拒绝的形式抛出,导致程序崩溃。可以通过以下步骤解决:
- 全局捕获未处理的Promise拒绝
在应用入口或数据库模块中添加全局监听,拦截所有未捕获的Promise错误,避免程序直接退出:
process.on('unhandledRejection', (reason, promise) => { logger.error(`未处理的Promise拒绝: ${reason instanceof Error ? reason.message : reason}`); // 可选:添加重连逻辑或告警通知 });
- 完善Mongoose连接的错误处理
扩展dbConnect函数的错误处理逻辑,同时为连接实例添加更详细的错误监听,并可选添加重连机制:
async function dbConnect () { try { await mongoose.connect(process.env.MONGODB!, { dbName: 'site', serverSelectionTimeoutMS: 5000 // 设置连接超时时间,避免驱动长时间重试 }); mongoose.connection .on('error', (err) => { logger.error(`数据库连接错误: ${err.message}`); // 可选:触发重连 setTimeout(dbConnect, 5000); }) .once('open', () => logger.log('Connected to database')); } catch (err) { logger.error(`DB连接失败: ${err instanceof Error ? err.message : err}`); // 连接失败后自动重试 setTimeout(dbConnect, 5000); } }
通过以上处理,既能捕获初始连接错误,也能拦截驱动层面的异步拓扑错误,避免程序因未处理的Promise拒绝崩溃。
内容的提问来源于stack exchange,提问作者Argon
相关产品推荐
相关产品推荐

