1

I am creating a Node / Express / Mongo app and would like to have an MVC-style file layout with a separate database service. I'd like my routes (controllers) to be fairly lean and simply call methods from elsewhere when I need to perform CRUD functions.

This great post had a lot of solid answers. I'll paste below the the answer from EddieDean that seems to be closest to what I'd like to do.

However, when I'm trying to reference the Users object defined in the mongo.js file in my someFile.js file, it comes back as undefined. I am pretty sure I am missing something obvious and would love to know what that is.

I can get a reference to the DB connection itself and call dbConn.Users.addUser(x) but I cannot directly call Users.addUser(x) as in the someFile.js example below.

This seems minor but I've spent too much time on this to not have an answer. Call it a knowledge vendetta.

Thanks.


mongo.js

const { MongoClient } = require('mongodb');
const config = require('./config');
const Users = require('./Users');
const conf = config.get('mongodb');

class MongoBot {
  constructor() {
    const url = `mongodb://${conf.hosts.join(',')}`;

    this.client = new MongoClient(url, conf.opts);
  }
  async init() {
    await this.client.connect();
    console.log('connected');

    this.db = this.client.db(conf.db);
    this.Users = new Users(this.db);
  }
}

module.exports = new MongoBot();

Users.js

class User {
  constructor(db) {
    this.collection = db.collection('users');
  }
  async addUser(user) {
    const newUser = await this.collection.insertOne(user);
    return newUser;
  }
}
module.exports = User;

app.js

const mongo = require('./mongo');

async function start() {
  // other app startup stuff...
  await mongo.init();
  // other app startup stuff...
}
start();

someFile.js

const { Users } = require('./mongo');

async function someFunction(userInfo) {
  const user = await Users.addUser(userInfo);
  return user;
}
Rob E.
  • 194
  • 3
  • 17

2 Answers2

1

What I did is simply put all my routes into start function. This isn't the best solution, but as starting point at least not the worst. So whenever you need an access to DB from some js file, just put them into start, so the mongo could establish the connection first.

So I want get the DB instance in /routes/users file.

const express = require("express");
const mongo = require("./mongo");
const app = express();
const PORT = process.env.PORT || 3000;

(async function start() {
  await mongo.init();

  app.use("/users", require("./routes/user")); 
})();
0

If someFile.js is required before the mongo.init method is called, the mongoBot instance will have been created, but Users will indeed be undefined. If you need to require someFile before the init method is called, you can move your destructured assignment to inside your someFunction method.

EddieDean
  • 1,806
  • 11
  • 13