I have an Express app that was created with express generator. I have a standard app.js
file that exports app. I also have a standard www
file that imports app
and is a starting point of the application:
const app = require('../app')
const debug = require('debug')('img-final:server')
const http = require('http')
const Mongo = require('../utils/dbConnection/dbConnection')
const port = normalizePort(process.env.PORT || '3000')
app.set('port', port)
/**
* Create HTTP server.
*/
const server = http.createServer(app)
/**
* Listen on provided port, on all network interfaces.
*/
async function startServer() {
try {
await Mongo.init()
debug('Connected correctly to DB')
server.listen(port)
} catch (err) {
debug(err)
}
}
startServer()
//some more unrelated code.
I also have a utility file for connecting to db dbConnection.js
:
const MongoClient = require('mongodb').MongoClient
class Mongo {
async init() {
const client = new MongoClient(`mongodb://localhost:27017/img-new`, {
useNewUrlParser: true,
useUnifiedTopology: true,
})
await client.connect()
this.db = client.db('img-new')
}
getConnection() {
return this.db
}
}
module.exports = new Mongo()
My problem is that when I start my app const app = require('../app')
is obviously running first, and wherever in my app route controllers I use getConnection()
, the connection is undefined
at that point because my Mongo.init()
is running after const app = require('../app')
.
I'm trying to understand how to solve it in sane way. I guess I can move all require
's and all other code inside startServer
after await Mongo.init()
, but it seems like there should be a better solution. Thank you.
Edit: Is this an OK solution?
const debug = require('debug')('img-final:server')
const http = require('http')
const Mongo = require('../utils/dbConnection/dbConnection')
async function startServer() {
try {
await Mongo.init()
const app = require('../app')
const port = normalizePort(process.env.PORT || '3000')
app.set('port', port)
const server = http.createServer(app)
server.listen(port)
} catch (err) {
debug(err)
}
}
startServer()
I have 1 solution but I'm not sure it satisfies your expectation.
In the getConenction
method you check if this.db
is undefined
. If it's a case, just call init() method then return this.db
. If not, you return this.db
directly. The code is like this:
async getConnection() {
if(!this.db) {
// connection to db is not established yet, we call `init` method
await this.init();
}
// this.db is defined here, we return the connection
return this.db;
}
And you don't have to call await Mongo.init()
in the startServer()
function
The previous answer by Đăng Khoa Đinh is the right direction. I add a bit of defensive coding to prevent multiple this.init()
being called at the same time. Note: I did not code against errors while connecting.
const MongoClient = require('mongodb').MongoClient
class Mongo {
init() {
// Gerard we set isConnected to a promise
this.isConnected = new Promise(async (resolve, reject) => {
const client = new MongoClient(`mongodb://localhost:27017/img-new`, {
useNewUrlParser: true,
useUnifiedTopology: true,
})
await client.connect()
this.db = client.db('img-new')
resolve();
});
}
isConnected = null;
async getConnection() {
if(this.isConnected === null) {
// connection to db is not established yet, we call `init` method
this.init();
}
// Now either the DB is already connected, or a connection is in progress. We wait.
await this.isConnected;
// this.db is defined here, we return the connection
return this.db;
}
}
module.exports = new Mongo()
The caller will then just do
connection = await Mongo.getConnection();
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.