0

Quoting only the important parts of the code. This is my server.js in the node backend server

//routes
const userapi = require('./api/routes/user');
//models
require('./api/models/userModel');

//use routes
userapi(app);

on my userapi which is my routes I call my userController

(function () {
    'use strict';

    module.exports = function (app) {
        var userCtrl = require('../controllers/userCtrl');

        app.post('/api/validate_user', function(req, res, next){
            userCtrl.validate_user(req, res);
        });
    }
})();

and this is my userController code. In the future, i will write a code that will handle all the transaction from my MongoDB.

'use strict';

var mongoose = require('mongoose'),
    model = mongoose.model('users'),
    brcpyt = require('bcrypt');

module.exports = function() {
    return {

        validate_user: function(req, res) {

            console.log('here');
        }
    }
};

The problem is, everytime I make a http request from my frontend. I get an error that says userCtrl.validate_user is not a function. My frontend can access the endpoints of '/api/validate_user' and the var userCtrl = require('../controllers/userCtrl') is a correct file path, but everytime that I type userCtrl to my routes it does not give me function validate_user

validate_user is not on the list

its located

0

2 Answers 2

1

You really don't need to be wrapping your modules in IIFEs. That said, the issue you are seeing specifically is because your userCtrl module is exporting a function that, when called, returns an object which will then have a validate_user member -- it's not exporting an object directly. Try checking the value of typeof userCtrl - it'll be function instead of an object, which is what you're expecting here :)

Specifically, the following should work with no changes to userCtrl:

var userCtrl = require('../controllers/userCtrl')()

Notice the extra parenthesis at the end? That will invoke the exported function and give you back an object with a validate_user method. This pattern is sometimes used when you'd like to pass some options to the module, like a factory pattern. For example,

const userCtrlFactory = require('../controllers/userCtrl') const userCtrl = userCtrlFactory({ option: value })

This, however, is not the best way to do so, you would be using classes for that.

I recommend you drop the IIFEs from your code ((function () {})()) and just have a top-level module.exports (like you did with the userCtrl) that exports either an object or a class, depending on what you need from it. For userCtrl, just export an object directly as you're not passing options or have a need for "instantiating" a controller more than once:

'use strict'; module.exports = { validate_user: ... };

0
1

require gives you the value assigned to module.exports, so your code is like:

var userCtrl = function() {
    return {

        validate_user: function(req, res) {

            console.log('here');
        }
    }
};

userCtrl.validate_user(...);

Do you see the bug now? userCtrl is a function, and therefore doesn't have a validate_user property ...

1
  • i see it now. so all i have to do is module.exports = { ..my functions.. } Commented Mar 12, 2018 at 10:25

Not the answer you're looking for? Browse other questions tagged or ask your own question.