0

I have an ExpressJS app where I have api.js in routes that manages connecting to Couchbase and then emits event couchbaseConnected that is awaited by init() function inside api.js.

Inside init() I want to push those exports.someFunction(req, res){return something;}. But when I just put these exports inside init() function, I get an error .get() requires callback functions but got a [object Undefined] so it seems like I am doing it wrong.

The question is how I can export functions from another function in NodeJS?

Here is the code:

//connecting to couchbase and emitting event on connection
couchbase.connect(dbConfiguration, function (err, bucket) {
  if (err) {
    console.log(err);
  }
    cb = bucket;
    eventEmitter.emit('couchbaseConnected');
});

//listening for the event and fire init() when it's there 
eventEmitter.on('couchbaseConnected', function (e) {
  console.log('Connected to Couchbase.'.green);
  init();
});

function init() {
 exports.getUserData = function (req, res) {
  if (req.user != undefined && req.user.meta != undefined) {
    res.json(200, {result: 'ok'})
  }
  else {
    res.json(401, {error: 'Unauthorized request.'})
  }
};
}

Here is the ExpressJS .get() that is located in app.js:

app.get('/api/user/data/:type', api.getUserData);
4
  • Show us that "push" code. Currently it just looks like a syntax error. Commented Aug 22, 2013 at 10:05
  • Where are you calling .get()? Show us the line that throws the error. Commented Aug 22, 2013 at 10:15
  • 1
    Is .get() run before api.init? Commented Aug 22, 2013 at 11:12
  • Are you calling connect when you start your app? Commented Aug 22, 2013 at 11:31

2 Answers 2

1

Here is the ExpressJS .get() that is located in app.js:

app.get('/api/user/data/:type', api.getUserData);

The error message .get() requires callback functions but got a [object Undefined] makes quite clear what happens: You require the API module, it starts to connect to the db, you are defining your express app by passing a non-existent property to .get - which fails, since init has not yet been called and getUserData has not yet been assigned. What you need to do is

var api = require('api');
eventEmitter.on('couchbaseConnected', function () {
    app.get('/api/user/data/:type', api.getUserData); // now it is available
});

However, this does not look like good code. Instead of loosely coupling them via that couchbaseConnected event you better should use explicit callbacks that are invoked with the requested values (i.e. the cb bucket, or the getUserData method). At least pass them as parameters to the emitted event.

Also, your setup is unconventional. I don't see why getUserData would need to be asynchronously defined - it should always be available. If the couchbase connection failed, I would not expect the /api/user/data/ service to not exist, but to respond with some 500 internal server error message.

Sign up to request clarification or add additional context in comments.

Comments

0

This is an answer that I have made some assumptions as the data provided by you is not sufficient to know what you are doing when you start your app.

I would suggest some change in code:

module.exports.connect = function(callback){
   couchbase.connect(dbConfiguration, function (err, bucket) {
      if (err) {
         console.log(err);
         callback(err);
      }
      cb = bucket;
      module.exports.getUserData = getUserData();
      callback(err); //just callback with no error as you don't require to send the database 
   });
}

function getUserData(req, res){
    if (req.user != undefined && req.user.meta != undefined) {
         res.json(200, {result: 'ok'})
    }
    else {
         res.json(401, {error: 'Unauthorized request.'})
    }
};

and in your app.js file where you are starting the app just do this

var api = require('./api');
api.connect(function(error){
    if (error) throw error;
    app.listen(3000);
    console.log('Express started on port 3000');
});

And then you can continue doing exactly what you were doing. It should work.

I have assumed that you are not explicitly calling the connect or its equivalent when you are starting the app.....So your getting that error.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.