What I usually use is something like this:
- src/
- main.js
- modules/
- [controllers]
- [models]
- database.js
- [script variados: util.js, http-server.js, socket-server.js, etc]
- views/
- [templates: mustache|handlebars|whatever]
- routes/
- user.js (/user routes)
- admin.js (/admin routes)
- etc
- test/
- [units]
- [acceptances]
- etc
- util/
- [script empacotador do app]
- [scripts variados]
- package.json
- [yarn.lock|package-lock.json]
In database.js we will have the following:
'use strict';
const mongoClient = require('mongodb').MongoClient;
module.exports.isReady = new Promise(async (resolve, reject) => {
try {
//Connect MongoDB
let database = await mongoClient.connect(
'mongodb://localhost:27017', {useNewUrlParser: true}
);
console.log('Connected successfully');
//Select and return database connection
let db = database.db('dataPOA');
module.exports.conn = db;
resolve();
}
catch (err) {
reject(err);
}
});
The idea is to open a permanent connection at the beginning of the application. This connection will never be closed, you will reuse it throughout your app.
As the connection set-up is asynchronous we need a way to identify that the connection is ready for use and that we can start our application, hence the use of Promise
isReady
(in module.exports.isReady
). The promise will only be resolved once the connection has been established.
Keeping in mind that the start point of the application is the file main.js
, in it we will have something like this:
'use strict';
const DB = require('./modules/database');
DB.isReady.then(async () => {
console.info('Datbase is ready');
// let server = HttpServer();
// socket server
// um arquivo qualquer que faz algo com a db
require('./modules/dosomething');
// mais requires
// etc
}).catch((err) => {
console.error('damn', err);
process.exit(1);
});
modules/dosomething
is any file, in it we have an example of how you will use the pre-established connection:
'use strict';
// dosomething.js
const DB = require('./database');
const collection = DB.conn.collection('maybeMongodbIsNotTheBestChoice');
// obs poderíamos usar async/await aqui sem problemas
// caso isso estivesse encapsulado em uma funćão async
collection.insertMany([
{name: 'afasdfasdfa'},
{name: 'erqwqwerwqerwqer'}
]).then(() => {
return collection.find({}, {limit: 5}).toArray();
}).then((res) => {
console.info(res);
});
And it's basically this, whenever you want to use the database you will require modules / database.js and use [DB].conn
. The crucial difference of this model to yours is that here DB.conn.[algum método]
( DB.conn.collection('minhacollection')
) does not establishes a new connection to the database, only reuses what was done in main.js
on the first require of% with%. In your example time we call modules/database.js
we are establishing a new connection to the bank and mongodb's own documentation already recommends avoiding this pattern.
I also have an example on link , just clone the project, run npm | yarn install inside the main folder and run mongodbConnection.collection('minhacollection')
.
Finally I hope it is clear that although the example uses node src/main.js
this template is not restricted to it. In dbs like mysql or sqlite you can (and I recommend) use a similar pattern, with the appropriate changes of course. For example, using mongodb
you not only want to wait for the connection to be established, but also that all your tables, views, triggers, etc., have been created before you start using the connection. For this we would need to adapt the mysql
so that it only calls the isReady
after all its resolve
(and similar) have completed.