【发布时间】: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 });
});
(请注意,当我更好地了解这一切是如何工作的时,我会将route 和middleware 处理移出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.connect()函数块中包含对数据库的后续调用(我无法将整个应用程序包装在该函数中)或 - 他们在
MongoClient.connect()功能块内调用app.listen()(这也是不可行的,因为我用express()和http和socket.io做了几件事)
环境:
node v14.18.1
"mongodb": "^4.1.4" (native driver)
编辑:
我根据this article 在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;
}
});
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