关闭MongoDB连接时触发Topology destroyed错误的问题
解决MongoDB "Topology was destroyed" 错误
问题根源
你碰到的这个报错核心原因有两个:
- 频繁创建/销毁连接:你的每个数据库方法(
checkUserID、getAccessToken)里都重复调用client.connect()和client.close(),但MongoDB客户端的设计逻辑是复用连接池,而非每次操作都新建、销毁连接,这种做法不仅低效,还容易触发拓扑销毁的错误。 - 时序冲突:在
checkUserID的Promise回调里调用client.close()后,后续执行getAccessToken时,客户端已经被销毁,再尝试连接自然会报错。
修复方案
我们需要重构数据库模块,让客户端只初始化一次并保持长连接,仅在所有操作完成后统一关闭连接,而非每个方法单独处理。
第一步:修改dbNew.js
const { MongoClient } = require('mongodb'); // 替换成你的实际MongoDB连接字符串 const uri = 'mongodb://localhost:27017/'; const client = new MongoClient(uri); // 缓存数据库实例,避免重复连接 let dbInstance; // 初始化数据库连接(仅执行一次) async function initDB() { if (!dbInstance) { await client.connect(); dbInstance = client.db("over_ride"); console.log("MongoDB连接成功"); } return dbInstance; } module.exports = { checkUserID: async function(userID){ const db = await initDB(); const collection = db.collection("users"); const checkCount = await collection.find({user_id:userID}).count(); return checkCount > 0; // 直接返回布尔结果,简化逻辑 }, getAccessToken: async function(userID){ const db = await initDB(); const collection = db.collection("users"); const result = await collection.findOne({user_id:userID}); console.log(result); // 用可选链避免字段不存在时抛出错误 return result?.social_media?.viber?.access_token; }, // 统一关闭连接的方法,在所有操作完成后调用 closeDB: async function() { await client.close(); console.log("MongoDB连接已关闭"); } };
第二步:修改test.js
const db = require('./dbNew'); // 用async/await简化异步逻辑,避免嵌套Promise async function run() { try { const isExist = await db.checkUserID(124214); if(!isExist){ const accessToken = await db.getAccessToken(810191770); console.log("获取到的AccessToken:", accessToken); } } catch (err) { console.error("操作出错:", err); } finally { // 所有操作完成后再关闭连接 await db.closeDB(); } } run();
关键优化点说明
- 连接池复用:MongoDB客户端默认维护连接池,初始化一次后所有方法共享连接,既提升性能又避免拓扑销毁问题。
- async/await语法:替代嵌套Promise,让代码逻辑更清晰,彻底解决时序冲突。
- 统一关闭时机:仅在所有数据库操作完成后(比如应用退出时)调用关闭方法,避免提前销毁客户端。
- 可选链容错:
result?.social_media?.viber?.access_token能有效避免字段缺失时的报错。
这样修改后,你就不会再遇到Topology was destroyed的错误,同时数据库操作的效率也会有所提升。
内容的提问来源于stack exchange,提问作者Hein Min Thant
相关产品推荐
相关产品推荐

