2

I want to reuse all my servise and controllers and I was achieving this with extending class. I'm calling the class of Controller and service all the way up from a router. everything looks fine while creating instance of class, but when I send request to sign in route it says there is no this.servise or this.dto which is i passed to the constructor while creating this instance of object

import express from "express";
const router = express.Router();
import UserController from "../../controllers/user.controller";
import UserService from "../../services/user.service.js";
import {UserDto} from "../../dtos/user.dto.js";
import User from "../../models/User.js";

const userService = new UserService(User);
console.log(userService, UserDto);                             // successfully logged
const userController = new UserController(userService, UserDto);
console.log(userController);                                   // successfully logged
router.post('/signup', userController.signup);
router.post('/signin', userController.signIn);
router.post('/signout', userController.signOut);
router.get('/all', userController.getAll);

router.route("/:id")
    .get(userController.get)
    .post(userController.create)
    .patch(userController.update)
    .delete(userController.delete);

export default router;
export default class UserController extends MainController {
    async signIn(req, res) {
        try {
            const {email, password} = req.body;//await this.dto.login(req.body);
            const result = await this.service.signIn(email, password); // TypeError: Cannot read properties of undefined (reading 'service')
            return res.status(201).json({message: "successfully signed in", token: result.token, user: this.dto.output(result.user)});
        }
        catch(err){
            sendError(res, err);
        }
    }

I've reviewed my knowledge of how nodejs modules work, but I can't figure out what the problem is.

Who can explain me this situation, please!?

Thank you in advance!

5
  • You didn't define a constructor in UserController to set the field... Commented Nov 30, 2022 at 12:59
  • I did it MainController class and i did it too here with super when i tried to fix the issue, but it didn't help Commented Dec 1, 2022 at 10:43
  • Where is your call to super? I can't see it in your code (?). Perhaps also share the super class. Commented Dec 1, 2022 at 11:44
  • There's no need for a call to super if you don't have a constructor defined. I assume that MainController has an appropriate constructor... Commented Dec 1, 2022 at 16:52
  • 1
    yeah MainController has it. I just forget to bind, my question is answered thank you all for helping me guys! Commented Dec 2, 2022 at 12:06

1 Answer 1

1

You forgot to use .bind() when passing the references to the methods to the Express router. So who knows what the value of this will be when Express tries to call them (in JS, this doesn't work like other variable names, it doesn't use lexical scoping, what the value will be depends on the calling code).

Change your code to e.g.

router.post('/signup', userController.signup.bind(userController));

This will ensure that this is set to your userController object when the function gets called (bind() is a method available on all function objects that returns a new function with a fixed this value).

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

3 Comments

yeah, thank you it works, do you any efficient idea for not repeating all binds
Not really :( personally I just don't do it like that, I don't use classes, just modules and normal functions... and since there's no "this" in them (just references to module-level variables), I also don't need "bind"...
Ok, thank you!. I was using modules too, but I like classes from other language :-)

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.