MongoDB报Topology was destroyed错误 写入前连接提前关闭原因查询
根本原因
该报错的核心诱因是cursor.forEach不支持等待异步回调执行完成:
- 不论是JS原生的
Array.prototype.forEach还是MongoDB Node.js驱动提供的cursor.forEach,设计上都没有处理返回值为Promise的回调逻辑。你给forEach传入async函数时,它只会按顺序触发每个回调,不会等待回调内部的await异步操作(如代码中的findOne、updateOne)全部执行结束,就会把自身的执行标记为完成 - 这就导致外层的
await cursor.forEach(...)会提前返回,直接执行后续的client.close()关闭数据库连接,此时还在pending状态的updateOne操作失去了可用的数据库连接,最终抛出MongoError: Topology was destroyed错误
修复方案
将游标转为数组后使用for...of遍历,即可正常等待所有异步操作执行完成,同时建议增加try/finally块保证异常场景下连接也能正常关闭:
module.exports.handler = async event => { const client = await MongoClient.connect( MONGO_URL, { useNewUrlParser: true } ) try { const db = client.db() // 先将游标转为数组再遍历 const docs = await db.collection('test').find().project({ _id: 1, pro: 1 }).toArray() // for...of 支持正常等待异步操作 for (const doc of docs) { if (!doc.elem) continue const data = doc.elem for (const provider of data) { const exist = await db .collection('public_profiles') .findOne({ _id: provider.publicProfileID }) if (_.isEmpty(provider.publicProfileID) || exist === null) { await db .collection('test') .updateOne( { _id: doc._id }, { $pull: { providers: { publicProfileID: provider.publicProfileID } } } ) } } } console.log('providers deleted') } finally { // 无论执行是否报错都关闭连接,避免连接泄漏 await client.close() } }
内容的提问来源于stack exchange,提问作者Gajiu
相关产品推荐
相关产品推荐

