0

I am trying to add a method loadSiteSettings to express module

     In app.js


        var express = require('express');
        var path = require('path');
        var mongoose = require('mongoose');

        //Set up default monggose connection for mongo db
        var mongoDB = 'mongodb+srv://***:*****@cluste******j.mongodb.net/cms?retryWrites=true&w=majority';
        mongoose.connect(mongoDB,{useNewUrlParser: true});
        //Get the default connection
        var db = mongoose.connection;

        //Bind connection to error event (to get notification of connection errors)
        db.on('error',console.error.bind(console, 'MongoDB connection error:'));///????????

        var app = express();

///////////////////////////////////////////////////////////
       var indexRouter = require('./routes/index');

        app.loadSiteSettings = async function()
        { 
          let setting = await db.collection('settings').findOne();
          app.locals.siteSettings = setting;
        }

        app.loadSiteSettings();
//////////////////////////////////////////////////////
        module.exports = app;



Index.Js for router

var express = require('express');
var router = express.Router();
var app = require('../app');
var util = require('util');
/* GET home page. */
router.get('/', function(req, res, next) {
  res.render('index');
});
///////////////////////////////////////////
router.get('/reloadSettings', function(req,res,next){
    app.loadSiteSettings();
})
///////////////////////////////////////

module.exports = router;

so problem lies here, when server start it calls app.loadSiteSettings() in app.js but when i use route '/reloadSettings' it seems app is undefined in index.js

user3209130
  • 362
  • 5
  • 13

1 Answers1

0

This is an issue with circular dependencies and module.exports. This answer shows the same problem.

What's happening is app.js is required first and starts processing. The important thing to understand is that a file pauses execution while requiring a new file.

So when app.js requires ./routes/index, it has not finished processing, and has not reached module.exports = app. This means that when your routes file requires app.js, it's requiring it in its current state, which is the default export {}.

Thankfully there's a very simple fix:

// can be imported and tested separately from the app
const loadSiteSettings = function() { 
    return db.collection('settings').findOne();
}


router.get('/reloadSettings', async function(req,res,next){
    let settings = await loadSiteSettings();
    req.app.locals.siteSettings = settings

    res.send(200); // signal the response is successful
})

This explains the issue in a lot more depth in case you're interested

HMilbradt
  • 3,980
  • 16
  • 31
  • I tried above like this app.js `const loadSiteSettings = async function() { let setting = await db.collection('settings').findOne(); app.locals.siteSettings = setting; } loadSiteSettings(); module.exports = {app:app,loadSiteSettings:loadSiteSettings};` again in route file index.js `var a = require('../app'); var app = a.app; /* GET home page. */ router.get('/', function(req, res, next) { res.render('index'); }); router.get('/reloadSettings', function(req,res,next){ // a.loadSiteSettings(); })` a is still undefined – user3209130 Sep 23 '19 at 14:54
  • I'm sorry, When I originally posted it I missed a critical line: ```req.app.locals = settings```. See the post for the updated code! Because app is available on the ```req``` object, you do not need to require it anywhere in your routes/controllers. – HMilbradt Sep 23 '19 at 17:12
  • But what i was trying to achieve is load setting in app initial boot, and if i change settings then i can reload app.locals.settings with the changes instead of passing in every request – user3209130 Sep 27 '19 at 12:57
  • ```req.app``` and ```app``` both point to the same object. ```req.app``` is provided as a convenience for faster access, and removes the need for an import. Your route ```/reloadSettings``` already receives the ```req``` object, so this is definitely a more "express" way of handling this. – HMilbradt Sep 27 '19 at 16:09