Struggling to pass express.js router requests and responses to a class method

I am struggling with setting up an Express JS router.

I am facing difficulty passing req and res to my class method.

Not Working app.get('/', controller.index)

Working

app.get('/', (res,req) => controller.index(req,res)

The routing flow I implemented follows this path:
app.js (Main file) > /routes/index.js > /routes/user.route.js > /controllers/user.controller.js > /services/user.services.js

app.js

import express from 'express';
import cors from 'cors';
import routes from './routes';
import db from './models';
import dotenv from 'dotenv';

dotenv.config();
const app = express();
const port = process.env.PORT || 3001;

app.use(cors())
app.use(express.json());
app.use(express.urlencoded({ extended: false }));

// Database Initialize
db.sequelize.sync()
.then(() => {
    console.log("🚀 Database Connected.");
}).catch((err) => {
    console.log("❌ Failed Connect to Database");
})

// Router
app.use(routes);

//global dir
global.__basedir = __dirname;

app.enable("trust proxy");

app.listen(port, () => {
  // logger.info("Checking the API status: Everything is OK");
  console.log(`🚀 App listening on port ${port}`);
})

routes/index.js

import express from "express";
import appRoutes from './app.routes';
import roleRoutes from './role.routes';
import userRoutes from './user.routes';
import authRoutes from './auth.routes';

const app = express();

// App Routes
app.use('/app', appRoutes);
// Role Routes
app.use('/role', roleRoutes);
// User Routes
app.use('/user', userRoutes);
// Auth Routes
app.use('/auth', authRoutes);

export default app;

routes/user.routes.js

import express from 'express';
import userController from '../controllers/user.controller';
import validateAuth from '../middlewares/validateAuth';

const app = express();
const controller = new userController;

app.get('/', controller.index);

export default app;

controllers/user.controller.js

import userServices from "../services/user.services";
import baseController from "./base.controller";

export default class userController extends baseController {
    constructor() {
        super(new userServices());
    }
}

controllers/base.controller.js

import response from "../helpers/response";
import lang from "../helpers/lang";
import dotenv from "dotenv";
dotenv.config();

export default class baseController {
    constructor(service) {
        this.service = service
    }

    /**
     * Index
     * Get all data with pagination
     */
    async index(res, req) {
        try {
            const data = await this.service.paginate(req.query);
            if(data) {
                return response.success({
                    res,
                    message: lang[process.env.LANG].DATA_LOADED,
                    data
                });
            } else {
                throw new Error(lang[process.env.LANG].REQUEST_FAILED);
            }
        } catch(err) {
            console.log(err)
            return response.error({
                res,
                message: err.message,
            });
        }
    }
}

services/user.services.js

import baseServices from "./base.services";
import db from "../models";

export default class userServices extends baseServices {
    constructor() {
        const attributes = [
            "roleId",
            "appId",
            "username",
            "password",
            "name",
            "phone",
            "email",
            "isActive",
        ];
        super(db.user, attributes);
    }

    /**
     * Paginate
     * @param {{
     *  search: string,
     *  limit: number,
     *  offset: number,
     *  sortBy: string,
     *  orderBy: string,
     *  user: object
     * }} data
     * return Promise
     */
    paginate(data) {
        const { search, limit, page, sortBy, orderBy, user } = data;

        const offset = limit
            ? parseInt(limit) * parseInt(page) - parseInt(limit)
            : 0;

        let filter = {};
        if (search)
            Object.assign(filter, { name: { [Op.like]: `%${search}%` } });

        const condition = {
            where: filter ? filter : "",
            order: sortBy ? [[sortBy, orderBy]] : [["name", "asc"]],
            limit: limit ? parseInt(limit) : 10,
            offset,
            include: ["role", "app"]
        };

        return this.model.findAndCountAll(condition);
    }
}

services/base.services.js

import db from "../models";
const Op = db.Sequelize.Op;

/**
 * Base Services Class
 */
export default class baseServices {
    constructor(model, attributes = []) {
        this.model = model;
        this.attributes = attributes
    }
}

Response

Not Working app.get('/', controller.index)
Error Response

Working

app.get('/', (res,req) => controller.index(req,res)

Success Response

I attempted changing const app = express() and const app = express.Router() but the issue persists.

Answer №1

I've noticed a couple of issues in your code:

  1. One problem is that you're losing the controller object in the index method due to how you are passing it.

  2. There seems to be confusion with the order of the (req, res) arguments as well.

The controller.index() method defines them in reverse order:

async index(res, req) { ... }

This causes an issue when you call:

app.get('/', controller.index)

since Express passes the arguments as

(req, res)</code while your method expects them as <code>(res, req)
.

That's why this alternative works:

app.get('/', (res,req) => controller.index(req,res));

because it reverses the arguments again.


To fix this, update the method like this:

async index(req, res) { ... }

to align with how Express delivers the arguments and ensure they match up correctly.

Moreover, since your controller object has instance data and the index method uses this, you should also make sure the index method receives its instance properly by modifying to:

app.get('/', controller.index.bind(controller));

Answer №2

You must adhere to the proper MVC design pattern and echo after me, your app.js file should look like this:

require ('dotenv').config();
const routes =  require('./routes');
const express = require('express');
const app = express();
const bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({ extended: true }));
const cors = require('cors');
const db = require('./models');

const port = process.env.PORT || 3001;

app.use(cors());
app.use(express.json());

// Database Initialization
db.sequelize.sync()
.then(() => {
    console.log("🚀 Database Connected.");
}).catch((err) => {
    console.log("❌ Failed Connect to Database");
})

// Routing
app.use(routes);

//global dir
global.__basedir = __dirname;

app.enable("trust proxy");

app.listen(port, () => {
  // logger.info("Checking the API status: Everything is OK");
  console.log(`🚀 App listening on port ${port}`);
})

The structure of routes/index.js should be as follows:

const router = require("express").Router();

router.use('/app', require(./app.routes"));
router.use('/role', require("./role.routes"));
router.use('/user', require("./user.routes"));
router.use('/auth', require("./auth.routes"));


module.exports = router;

All your routes files should follow a similar format

user.routes

const userController = require("whatever the location");
const router = require("express").Router();

router.post("/example", userController.controller);

module.exports = router;

The userController file:

const userServices = require("what ever the location");

const controller = async (request, response) => {
    try {
        //code goes here
        await userServices.addUser(
        {
                "name": "ALI",
                "gender": "MALE",
        }
    )
    } catch (error) {
        console.log(error);
        response.status(500).json({
            error: "Something went wrong",
        });
    }
}

module.exports = {
    controller
}

Lastly, the userServices file is:

const user = require("what ever the location");

const addUser = async (data) => {

    return new Promise((resolve, reject) => {
        new user(data)
            .save()
            .then((data) => resolve(data))
            .catch((err) => reject(err));
    });

}

module.exports = {
    addUser
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the level of visibility in Nextjs?

Is it safe to expose the sources of files located in the 'pages/' directory? For instance, if you set up a page specifically for administrators at pages/admin and restrict access through Middleware, does this enhance security measures? ...

Testing a React component that uses useParams: A step-by-step guide

I've been working on creating a BBS App using TypeScript, React, React Router, and React Testing Library. However, I've encountered an issue where a component utilizing useParams is not passing a test. Interestingly, it seems to be working correc ...

Recreating elements in ng-repeat using ng-click conditionally

I am attempting to swap an anchor tag with an image when clicked by the user. The code snippet I'm using looks like this: <div ng-repeat="postpart in currentPost.parts "> <div ng-if = "!postpart.isclicked"> <img ng-src= ...

unusual behavior observed in addEventListener

I have recently delved into learning about the DOM. I have a project in mind where I want to create a website with buttons that, when clicked, play different drum sounds. As part of my experimentation with JavaScript, I wanted to explore the this keyword. ...

AngularJS - Unusual outcomes observed while utilizing $watch on a variable from an external AngularJS service

Within the constructor of my controllers, I execute the following function: constructor(private $scope, private $log : ng.ILogService, private lobbyStorage, private socketService) { this.init(); } private init(){ this.lobbyData = []; this.initial ...

Converting information from a model into individual variables

I'm a newcomer to typescript and angular, and I've been attempting to retrieve data from firebase using angularfire2. I want to assign this data to variables for use in other functions later on. I am accustomed to accessing object members using d ...

Adjust the size of the text within the div element as needed

Here is my code on jsFiddle where I am dynamically changing the text font to fit in the div. Everything is working perfectly fine. Currently, the text is within a span element, but I would like to remove the span and have the same functionality. However, w ...

Adjust the background color of the table header in Google Charts

Is it possible to dynamically change the background color of the header row (and rows) in Google Charts based on values from a PHP database? The documentation suggests using the following code: dataTable.setCell(22, 2, 15, 'Fifteen', {style: &a ...

Determine the success of an SQL query in Node.js

I've created a basic API using nodejs to connect my Flutter app with a SQL Server database, but I have a question. How can I verify if the query was successful in order to return different results? I'm attempting an update after a successful in ...

extract element from a string with the help of jquery

When using AJAX to request HTML from a page, the process involves sending a request like this: function getHTML() { //set ajax call var options = { url: '/Controller', type: 'GET', d ...

How to extract and display data when clicking on a Bootstrap switch

I have integrated BootStrap Switch like this: <?php while ($arr = mysql_fetch_array($res)) { ?> <td class="center"> <?php if ($arr['status'] == 1) { ?> <input class="switch" type="checkbo ...

Using Styled Components to achieve full width for input tag in relation to its parent

I am working with an input field that has a specific width set. My goal is to increase the width of this input field to 100% by selecting it from its parent component. Is there a way to achieve this without passing an explicit width prop in the styled c ...

Dealing with Expressjs error messages: When sending data that is strictly a string,

It has been quite challenging to find information on this topic, as most inquiries involve incorrectly serialized objects. I am attempting to send a string, not an object. Here is the request right before it is sent off. The payload can be properly handle ...

JavaScript and jQuery validation issues persisting

Here is the HTML code I am using: <script src="js/validate.js"></script> <label>FIRST NAME:</label> <td> <input type="text" class="firstname" id="firstname" onKeyUp="firstname()" /> </td> <td> <label id=" ...

Adding an image within the body of text in a Django model, where both the text and image coexist

I am currently seeking a method to seamlessly insert an image within the text of my Django-powered blog. My goal is to achieve a layout similar to the one showcased in this example: https://i.stack.imgur.com/cFKgG.png The desired layout consists of two c ...

The ultimate execution point is collection.findOne

I am struggling to comprehend why the command located at the bottom is being executed before the code within the mongoose/function. router.post("/path", function(req, res, next) { for(var i = 0; i < req.body.getname.length; i++) { Bun.find ...

Looking to transfer data between files in Nodejs

This is the routes.js file I am working with const express = require('express'), router = express.Router(), loginHandler = require('../handler/loginHandler'), router.get('^/:userId/:userType/:sessId/:lang/:orgId/:merchantI ...

What is the best way to update a JSON object in a file using the file system module in Node.js?

Recently, I've been learning about read and write operations using the 'fs' module in Node.js. Here's my specific situation: I have a file containing data structured like this: [ { "Pref":"Freedom", "ID":"5545" }, { "Pref" ...

Exploring the functionality of promises in JavaScript

Currently, I am using the most recent version of Angular. The code snippet I've written looks like this: $q.all({ a: $q.then(func1, failHandler), b: $q.then(func2, failHandler), c: $q.then(func3, failHandler), }).then(func4); Is it guaranteed ...

javascript variable pointing to an unknown object

Below is the essential code snippet to consider: JS function ToggleRow(objTwistie, objRow) { if (objRow.style.display == "none") { objRow.style.display = ""; objTwistie.src = "../Images/SectionDown.gif"; } else { objRow.style.display = "n ...