0

I know there are lots of questions similar to mine but I could not find the best solution. I am creating a web app with node and rethinkdb. I want to organise different js files (modules) so that each has specific task. I have this query.js file whose query result must be passed to routes.js file. I have tried implement this in the following way.

query.js

//dependencies
var express = require('express');
var path = require('path');
var r = require('rethinkdbdash')({
  port: 28015,
  host: 'localhost',
  db: 'stocks'
});


var len;

//function to get companies list 
exports.clist = function(){
    r.table('company')
.run()
  .then(function(response){
     return response;
  })
 .error(function(err){
    console.log(err);
 })   
}
console.log(exports.clist[0].id)

//function to get number of entries in database
exports.clen = function(){
    r.table('company')
.run()
  .then(function(response){
      len = Object.keys(clist).length;
     return len;
  })
 .error(function(err){
    console.log(err);
 })   
}

routes.js

//dependencies
var express = require('express');
var request = require('request');
var path = require('path');
var r = require('rethinkdbdash')({
  port: 28015,
  host: 'localhost',
  db: 'stocks'
});

//query module
var query = require('./query')


clist = query.clist();
clen = query.clen();


//create router object
var router = express.Router();

//export router
module.exports = router;

//home page
router.get('/', function(req, res) {
    console.log('served homepage');
    res.render('pages/home');
});


//--companies page--//
router.get('/company', function(req,res){  

      console.log('served companies page')
      res.render('pages/company', {
        clist: clist,
        x:clen
      }); 
});

the console log in query.js is showing that cannot read property id of undefined.

Also I would like to know is there a way to directly pass the variables instead of using functions and then calling it. I apologise if the solution is obvious.

To summarise I want the query result which is an object to be accessible from routes.js file.

codeyashu
  • 55
  • 2
  • 7
  • As `exports.clist1` is an asynchronous method, you can't expect the result to be printed in the next line. Please follow my answer below and execute the code. – Aruna Oct 16 '16 at 10:32
  • As `query.js` is doing things asynchronously, I have updated this too to handle this properly. Please check the updated now. – Aruna Oct 16 '16 at 10:41

1 Answers1

0

Note: As exports.clist1 is an asynchronous method, you can't expect the result to be printed in the next line, hence comment this line and follow as below

//console.log(exports.clist[0].id)

You have to register a middleware to make this working, otherwise, query will be called only at the time of express server started and not at every request.

So you can do like this,

Hope you had something like this in your startup file (app.js),

var app = module.exports = express();

routes.js

//query module
var query = require('./query')
var app = require('../app');  // this should resolve to your app.js file said above

//clist = query.clist();
//clen = query.clen();

// middleware to populate clist & clen
app.use(function(req, res, next){
   query.companyList(function(err, data){
      if(!err) {
         req.clist = data.clist;
         req.clen= data.clen;
      }
      next();
   });
});

query.companyList(function(err, data){
      if(err) {
         console.log(err);
      } else {
         console.log(data.clist[0].id);
         console.dir(data.clist);
      }
   });


//create router object
var router = express.Router();

//export router
module.exports = router;

//home page
router.get('/', function(req, res) {
    console.log('served homepage');
    res.render('pages/home');
});


//--companies page--//
router.get('/company', function(req,res){  

      console.log('served companies page')
      res.render('pages/company', {
        clist: req.clist,
        x: req.clen
      }); 
});

Change your query.js like this,

//function to get companies list 
exports.companyList = function(next){
    r.table('company')
.run()
  .then(function(response){
     var list = {
       clist: response,
       clen: Object.keys(response).length
     };
     next(null, list);
  })
 .error(function(err){
    console.log(err);
    next(err);
 })   
};
Aruna
  • 448
  • 3
  • 12
  • As `query.js` is doing things asynchronously, I have updated this too to handle this properly. Please check the updated now. – Aruna Oct 16 '16 at 10:41
  • 1
    An alternate approach is that you return the promise from your companyList function and then you can send the response when the db has returned, e.g. router.get('/company', function(req,res){ query.companyList(...).then(result => { res.render('pages/company', { clist: result, x: Object.keys(result).length }); }); }); – JVDL Oct 16 '16 at 11:17
  • @Aruna Iconsole.log(req.clist[0].id) – codeyashu Oct 16 '16 at 11:29
  • why wont console.log(req.clist[0].id) gives me an error "Cannot read property '0' of unknown? I have decl – codeyashu Oct 16 '16 at 11:33
  • am sorry... i keep pressing enter.. @Aruna yep how can do that? also it says req is not defined. So I did var req = {} Is it wrong? – codeyashu Oct 16 '16 at 11:34
  • @codeyashu don't do like this, I will update the code now to print this – Aruna Oct 16 '16 at 11:36
  • after that middleware function – codeyashu Oct 16 '16 at 11:36
  • You should not add this after the middleware since the middleware will be called for each request from the client (browser). I will add the `console.log` a bit differently after the middleware. – Aruna Oct 16 '16 at 11:38
  • I have updated the code now and printing the id and then the whole object. In case of db error, it will print the error. – Aruna Oct 16 '16 at 11:41
  • @codeyashu You should treat asynchronous calls asynchronously and not synchronously as you did – Aruna Oct 16 '16 at 11:42