MongoDB:异步函数未完成或如何正确关闭与 mongoose 的连接

Posted

技术标签:

【中文标题】MongoDB:异步函数未完成或如何正确关闭与 mongoose 的连接【英文标题】:MongoDB: Async function doesn't end on complete or how to close connection properly with mongoose 【发布时间】:2020-09-10 05:25:18 【问题描述】:

这个问题与 MongoDB 和 mongoose 驱动程序更相关,而不是 async/await 代码本身。

我的*.js 文件中有以下代码:

const model1 = require("../../db/model1");
const model2 = require("../../db/model2");
const connection = require('mongoose');

async function f() 
    try 
        let token = await model2.findById(id) //find just one doc 
        let cursor = await model1.find().limit(5).cursor()
        for (let c = await cursor.next(); c != null; c = await cursor.next()) 
            //BLAH BLAH BLAH LOGIC
          
     catch (e) 
        console.log(e)
      


f().then(r => 
    connection.close();
    console.log('close');
    return r
);

所以问题是:

当我只使用一个 modelrequire (CommonJS) 时,函数以以下消息正确结束:Process finished with exit code 0,但是当我将第二个模型添加到文件时 (model2 in我的情况,但它可以是任何模型文件或 require 模型的另一个函数)然后函数不会结束。

这并不意味着connection.close() 不起作用,根据 WebStorm 的debug 控制台,来自console.log() 的消息 close 打印成功,但由于某种原因,该过程根本没有结束。 我在其他关于connection.close 的问题上看到过类似one 这样的问题,但没有一个与我的问题有关。文档说一个close() 就足够了,它会关闭池中的所有连接。

我导入的每个模型都具有以下结构,无一例外:

const mongoose = require('mongoose');
mongoose.Promise = global.Promise;

require('dotenv').config();
mongoose.connect(`mongodb://$process.env.login:$process.env.password@$process.env.hostname/$process.env.auth_db`, 
    useNewUrlParser: true,
    useFindAndModify: false,
    useUnifiedTopology: true,
    bufferMaxEntries: 0,
    retryWrites: true,
    useCreateIndex: true,
    w: "majority",
    family: 4
);

let schema = new mongoose.Schema(
    _id: 
        type: String
    ,
    any_field: 
        type: String,
    ,
,
    timestamps: true
);

let keys_db = mongoose.model('keys', schema);

module.exports = keys_db;

因为model 代码没有任何setTimeout 或除connect 之外的其他函数到DB 它不应该阻塞线程。所以我不明白这是怎么回事,我猜SO上的某个人已经面临类似的问题,可以为我提供一些澄清。或者它是异步函数的正常行为,我不应该看到它有问题?

【问题讨论】:

在每个模型文件中调用mongoose.connect 而不是在公共文件中只调用一次是否有任何特殊原因? @thammadam 是的,没有,猜是问题 我想这可能是个问题。尝试将mongoose.connect 移动到一个公共文件中。如果它确实解决了您的问题,请随时发布答案。 @thammada,是的,已经做到了。非常感谢您的建议,老实说,我刚刚看到它,而不是 40 分钟前。它可以节省我 30 分钟的时间,但至少我有能力自己解决这个问题,所以还不错吧? 我想最好的学习方法是通过你自己积累的经验:) 【参考方案1】:

我发现,在每个模型中使用connect 是一种不好的做法。不幸的是,it's very poorly described in mongoose 手册。

因此,这是我项目中架构不良的问题。所以,正确答案如下:

您应该(使用)connect 一次,然后将其导出,而不是在每个架构/模型文件中使用 connect

或者为每个核心/敏感功能建立单独的连接,例如,后端和前端的单独连接,但不是每个功能的每个连接(就像我做的那样)

正如我之前提到的,mongoose 文档对这种模式的描述很差,documentation for connection.close() 描述了这种方法,就像你可以一次性关闭所有连接一样。 (这实际上是正确的,但在这种情况下它对你没有帮助)

我还发现 Stack Overflow 上的这个问题对我的研究非常有用:

Export and reuse my mongoose connection across multiple models Mongoose and multiple database in single node.js project

【讨论】:

您实际上提到了mongoose.disconnect() 的文档,它在所有连接上内部调用connection.close(),可能值得一提的区别

以上是关于MongoDB:异步函数未完成或如何正确关闭与 mongoose 的连接的主要内容,如果未能解决你的问题,请参考以下文章

如何正确关闭MongoDB

如何正确关闭MongoDB

如何正确关闭MongoDB

WCF 的“使用”语句中的异常未正确关闭连接。如何关闭有故障的 WCF 客户端连接或有异常的连接?

SAP 未完成收货的采购订单如何关闭

linux 如何正确的关闭mongodb