Lionel Morrison
Lionel Morrison

Reputation: 596

Node.js ES6 Class unable to call class method from within class method when using Express.js

Nb. This is driving me a little nuts and I've been around the houses a few times. However I'm fairly new to ES6 and JS as a whole and fully understand that a JS Class is not like that of Classes found in other languages and might be approaching this completely wrong.

I'm running the following code which is using Express.js (v4.16.3) and body-parser (v1.18.2) on Node v8.9.0.

app.post('/api/v1/user/update', urlencodedParser, user.update);

The code calls 'urlencodedParser' which is acting as middleware to provide 'req' with 'req.body' so that I can pull out the form fields. 'user' is a class module that has been exported and contains all the functions for validation, updating etc. and looks something like this:

class Users {    
    update(req,res) {
        console.log('updating...');
        this.verifyUserIdentity();
    }

    verifyUserIdentity(req,res) {
        console.log('verify');
    }
}

module.exports = new Users;

Now if I were to run this code in node without Express like so:

var users = require('./modules/users');

users.update();

It all appears to execute and I get the following output on the CLI:

updating...
verify

If I wrap it all up in the app.post() (above) and use Postman to send a POST it executes the first method and stops dead after the console.log() with no error. It seems not to call verifyUserIdentity() and I get the following on the CLI:

updating...

If I modify the code as you see below and pass an array of methods to Express' middleware handler, it seems to work, but now I have to call verifyUserIdentity() separately, and doesn't solve the problem of how do I call another method from the same class, for instance a log() method.

class Users {    
    update(req,res) {
        console.log('updating...');
    }

    verifyUserIdentity(req,res,next) {
        console.log('verify');
        next();
    }
}

module.exports = Users;



app.post('/api/v1/user/update', [urlencodedParser, users.verifyUserIdentity], users.update);

Some my question: - Why isn't the original pattern working with Express? - has 'this' taken a hike because of the callback handlers? - Has this got something to do with Node v8.9.0? - Am I doing this all wrong?

Upvotes: 2

Views: 1800

Answers (1)

jfriend00
jfriend00

Reputation: 708126

You aren't getting a proper this pointer in your method.

Change this line of code:

app.post('/api/v1/user/update', urlencodedParser, user.update);

to this:

app.post('/api/v1/user/update', urlencodedParser, user.update.bind(user));

When you pass user.update, all it passes is a reference to the update() method and the association with the user object is lost. When Express then calls it as a normal function, this will be undefined (in strict mode) inside that method rather than your user object. You can use .bind() to solve this issue as shown above.

FYI, this has nothing specifically to do with Express. It's a generic issue when passing a reference to an obj.method as a callback that you want some code to store and then call later. You have to "bind" the object to it so that it gets called with the right object context.

Upvotes: 11

Related Questions