You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

关闭MongoDB连接时触发Topology destroyed错误的问题

解决MongoDB "Topology was destroyed" 错误

问题根源

你碰到的这个报错核心原因有两个:

  1. 频繁创建/销毁连接:你的每个数据库方法(checkUserID、getAccessToken)里都重复调用client.connect()和client.close(),但MongoDB客户端的设计逻辑是复用连接池,而非每次操作都新建、销毁连接,这种做法不仅低效,还容易触发拓扑销毁的错误。
  2. 时序冲突:在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 05:15:52