从 MongoClient.connect() 导出未在其他模块中读取

Posted

技术标签:

【中文标题】从 MongoClient.connect() 导出未在其他模块中读取【英文标题】:Export from MongoClient.connect() is not being read in other module 【发布时间】:2021-09-17 07:11:45 【问题描述】:

我正在尝试在另一个模块中重用我的 MongoClient 连接,并且在导入时导出为 null。

index.js

import app from './server.js'
import pkg from 'mongodb'
const  MongoClient  = pkg

let db = null

async function listDatabases(client) 
  try 
    const dbList = await client.db().admin().listDatabases()
    console.log('Databases:')
    dbList.databases.forEach((db) => 
    console.log(` - $db.name`) // I see the databases here
 )
 catch (error) 
   console.error(error)
 


MongoClient.connect(uri, 
  useNewUrlParser: true,
  poolSize: 50,
  useUnifiedTopology: true,
)
 .then(async (client) => 
   listDatabases(client) // I see the databases here
   db = client
   app.listen(port, () => 
    console.log(`listening on port $port`)
  )
 )
.catch((err) => 
  console.error(err.stack)
  process.exit(1)
)

export default db

然后在 OrdersDAO.js 中,我正在导入 db 以便能够访问 db 和集合。我提到了这个***

import db from '../index.js'

static async getOrders() 
   try 
   // db is null here
   console.log('OrdersDAO.getOrders ~~~ made it to the OrdersDAO step 2', db)

   catch (e) 
    console.error(`OrdersDAO ~~~ Unable to get orders: $e`)
    return  e 
  

我做错了什么?

下面是我原来的异步函数和后续函数调用:index.js

const client = new MongoClient(uri, 
  useNewUrlParser: true,
  poolSize: 50,
  useUnifiedTopology: true,
)

async function connectToMongoDB() 
  try 
    await listDatabases(client)
    app.listen(port, () => 
    console.log(`listening on port $port`)
   )
  catch (e) 
    console.error(`Index.js ~~~ Unable to get database.collection: $e`)
  finally 
    console.log('Mongo Connection is closing ~~~~')
    await client.close()
  


connectToMongoDB().catch(console.error)

【问题讨论】:

【参考方案1】:

连接到数据库是一个异步操作,因此,它返回一个Promise。该函数内分配的任何内容只有在该承诺解决后才可用。但是,您将返回 db 对象 在承诺之外,因此 js 引擎不会等待,而是返回初始值,即 null。 这是我在最近的一个项目中实现的一个简洁的解决方案,它还考虑了连接超时:

db.js

const MongoClient  = require("mongodb");
const DATABASE_URL = require("./config");

async function connect() 
  const client = await MongoClient.connect(DATABASE_URL, 
    useNewUrlParser: true
  );
   const db =  client.db();
   return  client, db ;
 ;

module.exports =  connect, dbHelper: connect()

crud.js

const  dbHelper, connect  = require("./db");

async function reconnect() 
    return connect();
;

async function getConnectionOrReconnect() 
    let mongo = await Promise.resolve(dbHelper);
    if (!mongo.client.isConnected()) mongo = await reconnect();
    return mongo;


//other api functions here

在这里,我同时导出连接函数本身和连接结果(作为承诺)。与其他文件相比,我正在解析导入的连接,如果它超时,我将再次重新连接。

【讨论】:

但是通过连接池,我不应该每次需要客户端时都重新连接。? 这只是一个额外的好处(我从我的项目中复制粘贴它,由于某种原因我没有使用池)。重点是 db 对象从 db.js 文件中的 connect 函数内部作为 Promise 导出的方式,然后在另一个文件中解析。

以上是关于从 MongoClient.connect() 导出未在其他模块中读取的主要内容,如果未能解决你的问题,请参考以下文章

NodeJS - MongoClient.Connect 与数据库的 URL 不是默认的

DeprecationWarning: current URL string parser is deprecated解决方法

Nodejs中Mongodb的基本使用

node之mongodb的DAO

MongoDb 和 Node.js

MongoDB 集合连字符名称