【问题标题】:Cannot read property 'db' of undefined after defining MongoClient.connect() outside of app.js在 app.js 之外定义 MongoClient.connect() 后无法读取未定义的属性“db”
【发布时间】:2022-01-04 22:34:56
【问题描述】:

以前我有一个工作的、单文件的应用程序,它本质上是:

const express = require('express');
const app = express();
const http = require('http');
const server = http.createServer(app);
const io = require('socket.io')(server);
app.set('socketio', io);

import { MongoClient } from 'mongodb';

var mongo_client;

var connection_string = 'mongodb://localhost:27017' // for local development environment 

MongoClient.connect(connection_string, (err, client) => {
  if (err) {
    throw err;
  } else {
    mongo_client = client;
  }
});

/*

lots of middleware and route handling

*/

server.listen(PORT, () => {
  console.log(`running on port ${PORT}`);
});

在中间件中,在同一个文件中,我会调用数据库,例如:

var collection = mongo_client.db('users').collection('users');

var query = { };

var options = { };

  try {
    var user = await collection.findOne(query, options);
    return user;
  } catch (err) {
    console.log('error: ' + err);
  }

我正在进行重构,并将MongoClient.connect() 块放在自己的文件中。

config/database.js 现在看起来像:

const MongoClient = require('mongodb').MongoClient;

const { connection_string } = require('./environment_variables');

let mongo_client;

MongoClient.connect(connection_string, (err, client) => {
  if (err) {
    throw err;
  } else {
    mongo_client = client;
    console.log('FIRST:  mongo_client: ');
    console.log(mongo_client);
  }
});

console.log('SECOND:  mongo_client: ');
console.log(mongo_client);

module.exports = mongo_client;

要开始测试如何将其导入另一个文件,我在 app.js 中执行此操作:

const mongo_client = require('./config/database');

app.get('/', async (req, res) => {
  const query = { username: 'my name' };
  const collection = mongo_client.db('users').collection('users');   // <----- error is here, mongo_client is undefined    
  const result = await collection.findOne(query);
  res.json({ result: result });
});

(请注意,当我更好地了解这一切是如何工作的时,我会将routemiddleware 处理移出app.js

控制台日志是:

SECOND:  mongo_client:
undefined
FIRST:  mongo_client:
MongoClient {
// ... lots of mongodb client properties here  
}
UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'db' of undefined

所以看起来MongoClient.connect() 是异步的,因此在我尝试调用mongo_client.db('users').collection('users') 之前没有定义mongo_client

我的问题是:

  • 如何解决此问题?
  • 为什么在我从app.js 中提取MongoClient.connect() 之前没有发生这种情况?

我一直在阅读这样的文章:

MongoClient connection pooling

MongoClient docs

但他们似乎:

  • MongoClient.connect() 函数块中包含对数据库的后续调用(我无法将整个应用程序包装在该函数中)或
  • 他们在MongoClient.connect() 功能块内调用app.listen()(这也是不可行的,因为我用express()httpsocket.io 做了几件事)

环境:

node v14.18.1  
"mongodb": "^4.1.4" (native driver)

编辑:

我根据this articleconfig/database.js 中尝试了以下更改。

我替换了这个:

const MongoClient = require('mongodb').MongoClient;

const { connection_string } = require('./environment_variables');

let mongo_client;

MongoClient.connect(connection_string, (err, client) => {
  if (err) {
    throw err;
  } else {
    mongo_client = client;
  }
});
module.exports = mongo_client;  

用这个:

const MongoClient = require('mongodb').MongoClient;

const { connection_string } = require('./environment_variables');

const mongo_client = new MongoClient(connection_string);

const is_this_the_right_thing_to_do = async () => {
  await mongo_client.connect();
};

is_this_the_right_thing_to_do();

module.exports = mongo_client;

错误消失了,它正在返回一个结果,但我不确定这是否是正确的方法。

另外,我不确定如何在所有路由和中间件中使用 mongo_client 的单个实例。我尝试在app.js 的顶部要求它,希望之后需要的路由和中间件(在其他文件中)可以访问它,但他们没有,这是路由中间件中的错误:

UnhandledPromiseRejectionWarning: ReferenceError: mongo_client is not defined

另一个修改:

我已经发布了关于其他人的问题here 的答案,这可能是我正在寻找的,将在进一步测试后更新此帖子。

【问题讨论】:

    标签: node.js mongodb express node-mongodb-native


    【解决方案1】:

    如果您尝试从其他路由访问数据库(在您的情况下为 mongo_client.db("your database name here")),那么您可以在 app.js 或 index.js 中尝试类似的操作。

    const connectDB = async () => {
      await client.connect();
      db = client.db("greendeckData");
      app.use((req, res, next) => {
        req.db = db;
        next();
      });
      app.use("/get", getRouter);
    };
    
    

    您可以查看我找到解决方案链接的来源,here

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-29
      • 1970-01-01
      • 2016-01-10
      • 1970-01-01
      • 2020-04-06
      • 2022-06-16
      相关资源
      最近更新 更多