0

How do I make a var / object / module with a reference to a specific collection of the connected DB?

How do I make a module to export a reference to a specific collection to be used elsewhere:

Module connect-to-db.js

var MongoClient = require('mongodb').MongoClient;
var assert = require('assert');
var url = 'mongodb://<user>:<password>@..shard..mongodb.net:<port>/<collection>?ssl=true&replicaSet=..shard..&authSource=admin';

// This part works
MongoClient.connect(url, function(err, db) {
   assert.equal(null, err);
   console.log('Connected to external MongoDB server');
   // db.close(); // not called to keep connection open

   // How do I return db to the outside of this callback's scope 
   //   to exports.user?  
});

// This is the part that's not working
// How do I access db.collection('users').find() from outside this module
module.exports.users = MongoClient;
// this should return a reference to db.collection('users') in exports.users

// where should I return 

Then be able to query / write to that collection from anywhere (using dBconnection.users as below):

Main App server.js

var express = require('express');
var app     = express();
var dBconnection = require('./connect-to-db');
// is dBconnection is a reference to MongoClient.connection ?
// is dBconnection.users a reference to db.collection('users') ?

app.get('/db', function(req, res){

    // From here does not work
    records = dBconnection.users.find();
    // runtime error: cannot use .find() of undefined 
    // OR runtime error: find() is not a function of users 

    // Testing the query
    res.setHeader('Content-Type', 'text/plain');
    res.write('Attempting to display records\n');
    res.end(JSON.stringify(records, null, 2));
});

app.listen(3000, function () {
    console.log('Listening at port 3000')
});

In the end I want to make the module maintain the connection (even if dropped, maybe adding a .status property to exports to check the status) so that I can access it anytime elsewhere in server.js / other modules / other routes / views

Carl J du Preez
  • 77
  • 1
  • 10
  • How about exporting a `Promise` and using `await`: `const db = await require('./connect-to-db')` or `require('./connect-to-db').then((db) => {...})`? Or expose a function: `require('foxes').myConnect().then((foxes) => {...})` – ilyaigpetrov Mar 24 '17 at 16:16
  • Thanks for the suggestion - I'll have to read up a bit more on `promises` and `await` first :) – Carl J du Preez Mar 24 '17 at 16:24

1 Answers1

0

Nothing that is immediately available cannot be exported by a module in Node, because Node modules exports and the require() function are synchronous. (See this answer for more info: javascript - Why is there a spec for sync and async modules?)

What you can export, though, is a promise of the thing that you need in other requiring modules, like the db.collection('users').

For example you can do something like:

module.exports.users = new Promise((resolve, reject) => {
    someAsyncFunction((err, data) => {
        if (err) return reject(err);
        resolve(data);
    });
});

And then other modules will be able to use it like:

require('./the/module').users.then(users => {
  // use the users
});

or inside async functions:

let users = await require('./the/module').users;
// use the users

But you will not be able to export directly the value that is not available immediately when the module is required.

rsp
  • 107,747
  • 29
  • 201
  • 177
  • Thanks for pointing me in the right direction - I'll have to read up a bit more on `promises` and `await` and the link you provided first - I'm still a bit new to node.js – Carl J du Preez Mar 24 '17 at 16:31