Jaime Ginorio
Jaime Ginorio

Reputation: 153

Couldn't call method inside method controller in route Nodejs Express Typescript

I got two classes; authenticationRoutes.ts and authenticationController.ts. In authenticationRoutes I'm calling 'authenticationController.test', the 'authenticationController.test' method calls 'authenticationController.generateAccessAuthToken' method. Whenever I do this I get the following Error: Unhandled rejection TypeError: Cannot read property 'generateAccessAuthToken' of undefined

authenticationRoutes.ts
import { authenticationController } from '../controllers/authenticationController';

        //TEST ROUTE
        this.router.get('/users',  authenticationController.test);

authenticationController.ts


public test(req: Request, res: Response) {
        dbSequelize().User.findAll({
            where: {
                id: '0'
            },
            attributes: ['id']
        }).then((user: UserInstance[]) => {
            this.generateAccessAuthToken('0').then((response: any) => {
                console.log(response);
                res.send(response);
            });
        })
    }


generateAccessAuthToken(_id: any) {
        return new Promise(async (resolve, reject) => {
            await jwt.sign({ id: _id }, SECRET_KEY as string, function (err: Error, token: any) {
                if (err) {
                    reject(err);
                } else {
                    resolve(token);
                }
            })
        })
    }

I want to be able to do what I described without receiving an error.

Upvotes: 1

Views: 1548

Answers (2)

Zehava
Zehava

Reputation: 11

I faced the same issue and solved it :

public test = (req: Request, res: Response) => {
        dbSequelize().User.findAll({
            where: {
                id: '0'
            },
            attributes: ['id']
        }).then((user: UserInstance[]) => {
            this.generateAccessAuthToken('0').then((response: any) => {
                console.log(response);
                res.send(response);
            });
        })
    }

Upvotes: 1

Sergeon
Sergeon

Reputation: 6788

I think this will do the trick:

this.router.get('/users', authenticationController.test.bind(AuthenticationController));

Basically, when you have a class A with a method b, if you pass around A.b like:

const a = new A();
const b = a.b;
b(); // now 'this' is lost, any reference to `this` in b() code would be undefined

You are passing only the function. It has nothing to do with the A class now, it is just a function.

So, among other things, you can use bind to explicitly set the this context for a function:

const a = new A();
const b = a.b.bind(a);
b(); // so now b() is forced to use a as this context

I bet there are tons of duplicates about your issue, but I couldn't find anyone fast because the search is tricky (this binding in js has A LOT of issues).

Hope this helps.

Upvotes: 4

Related Questions