Trouble with loading TypeScript Express REST API routes!

I've been working on accessing data from my custom REST API, but I'm encountering an issue where the JSON data is not being displayed when I navigate to the endpoints. I have set up server, controller, and data controller classes in order to create and configure the API. The server and controllers load properly, however, when I visit an endpoint, it only shows the default React app page.

Here is the method for loading controllers in the server:

public loadControllers(controllers: Array<Controller>): void {
        controllers.forEach(controller => {
            console.log(controller, controller.path)
            this.app.use(controller.path, controller.setRoutes());
        });
    };

And here is the method for setting routes in the controller:

public setRoutes = (): Router => {
        for (const route of this.routes) {
            for (const mw of route.localMiddleware) {
                this.router.use(route.path, mw)
            };
            switch (route.method) {
                case Methods.GET:
                    this.router.get(route.path, route.handler);
                    break;
                case Methods.POST:
                    this.router.post(route.path, route.handler);
                    break;
                case Methods.PUT:
                    this.router.put(route.path, route.handler);
                    break;
                case Methods.DELETE:
                    this.router.delete(route.path, route.handler);
                    break;
                default:
                    console.log('not a valid method')
                    break;
            };
        };
        
        return this.router;
    }

This is an example route and handler in the DataController:

routes = [
        {
            path: '/locations',
            method: Methods.GET,
            handler: this.handleGetLocations,
            localMiddleware: [],
        },
]

async handleGetLocations (req: Request, res: Response, next: NextFunction, id?: number) {
        try{
            this.dbConn.initConnectionPool()
                .then((pool) => {
                    pool.query(`query here`)
                })
                .then((data) => {
                    res.send(data);
                })
        }
        catch(err){
            console.log(err);
        }
    }

Even though everything seems to be correct when logged in the console, the JSON data is still not displaying at the endpoints.

Answer №1

Initially, there seems to be an issue with the way this is handled in your code. Consider this example:

this.router.get(route.path, route.handler);

When router.handler points to a function like handleGetLocations() which relies on this referencing your object but it doesn't have the correct value. To address this, you can either use .bind() to bind this to your function or utilize arrow functions to maintain the proper value of this.

If this is incorrect, commands such as this.dbConn.initConnectionPool() within your handleGetLocations() function will fail due to this not being accurate.

The context provided in your question isn't sufficient for understanding what exactly this should reference and how to rectify the issue by declaring or structuring things appropriately.

You could potentially alter this code snippet:

routes = [
        {
            path: '/locations',
            method: Methods.GET,
            handler: this.handleGetLocations,
            localMiddleware: [],
        },
]

To something along the lines of:

routes = [
        {
            path: '/locations',
            method: Methods.GET,
            handler: this.handleGetLocations.bind(this),
            localMiddleware: [],
        },
]

However, this solution hinges on this having the correct value during array declaration, which isn't evident without more surrounding code.

Additionally, other issues exist in your code; like the lack of proper error handling in handleGetLocations(). If this.dbConn.initConnectionPool() encounters a rejection, your code presently lacks a valid handler. You need to either await the operation for the try/catch block to capture any rejections, or incorporate a .catch() following the .then() to manage rejected promises effectively.


Furthermore, incorporating a custom framework atop an existing one may introduce unnecessary complexity. Your custom system complicates the straightforward route declarations in Express, confounding rather than clarifying matters for others unfamiliar with your unique approach.


Lastly, revisiting this code snippet:

async handleGetLocations(req: Request, res: Response, next: NextFunction, id ? : number) {
    try {
        await this.dbConn.initConnectionPool()
            .then((pool) => {
                pool.query(`query here`)
            })
            .then((data) => {
                res.send(data);
            })
    } catch (err) {
        console.log(err);
    }
}

Seems to require several corrections. Primarily addressing the passing of this to the function, refining error handling to capture rejected promises adequately, gathering results from pool.query(), and sending error responses if necessary.

async handleGetLocations(req: Request, res: Response, next: NextFunction, id ? : number) {
    try {
        const pool = await this.dbConn.initConnectionPool();
        const data = await pool.query(`query here`);
        res.send(data);
    } catch (err) {
        console.log(err);
        res.sendStatus(500);
    }
}

Identifying potential issues within your framework layered upon another framework proves challenging given the constraints of the provided code. A simple test application featuring a single GET route might shed light on whether the Express route configuration is correct and whether the handler is invoked as expected. Unfortunately, without runnable code, debugging becomes formidable. As mentioned earlier, layering a custom framework onto an existing one appears unnecessarily complex with little observable benefit, necessitating meticulous debugging and maintenance efforts.

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

I am experiencing difficulty getting my CSS styles to apply to my application that is being rendered using zappa, express, and node.js

Here is a link to my code: http://pastebin.com/jcLRCrQr Although everything else seems to be working fine - CSS sheets loading correctly, JavaScript files functioning properly - I am facing an issue where the styles are not being applied. An odd thing I ...

Storing a MySQL query result in a global array in a Node.js environment

Just diving into the world of Node.js and Express, I'm trying to wrap my head around asynchronous functions and global variables. Specifically, I'm working on connecting to a MySQL database, fetching query results, and displaying them on a test.h ...

After removing an item from the component in reactJS, the immediate rendering of the dynamic component does not seem to be functioning correctly

I am currently creating a dynamic automobile inventory website from scratch using React.js, Express.js, and MongoDB. The data has been successfully loaded from the database and displayed in a tabular format on the client side. My next task is to enable use ...

There seems to be an issue with the connection between socket.io and the server

Recently, I encountered an issue while hosting my application on OpenShift with a custom domain. The problem arose when socket.io failed to download the client-side script, leading me to resort to using a CDN instead. However, this workaround has caused an ...

Ways to incorporate environment variable in import statement?

In my Angular v5 project, I have a situation where I need to adjust the import path based on the environment. For example, I have an OwnedSetContractABI file located in different folders for each environment - dev and production. In dev environment, the ...

Exploring the concept of kleisli composition in TypeScript by combining Promise monad with functional programming techniques using fp-ts

Is there a way to combine two kleisli arrows (functions) f: A -> Promise B and g: B -> Promise C into h: A -> Promise C using the library fp-ts? Having experience with Haskell, I would formulate it as: How can I achieve the equivalent of the > ...

Displaying only the initial entry in a MongoDB collection through Bootstrap modals

I am currently using NodeJS, Handlebars, and Bootstrap to develop a basic web application. The goal is to iterate through a MongoDB collection of simulated products and exhibit their respective fields. The data is being presented in "product cards" (see i ...

Angular 2 forms are displaying ngvalid when input fields are marked as nginvalid

The form displays ngvalid because I have included the code like this: <form novalidate class="pop-form" (submit)="signUp()" #regForm="ngForm"> <div class="group"> <input type="text" [(ngModel)]="signUpData.name" [ngMode ...

Leveraging Handlebars for templating in Node.js to incorporate a customized layout

app.js const exphbs = require('express-handlebars'); app.engine('handlebars', exphbs({defaultLayout: 'layout'})); app.set('view engine', 'handlebars'); app.use('/catalog', require('./routes/ ...

The getAuth() helper found in the api directory's Clerk retrieves the following data: { userId: null }

I'm completely stuck here.. Currently working with the clerk and I am looking to access the userId of the current user using the getAuth() helper. For more information, refer to the docs: pages/api/example.ts import { getAuth } from "@clerk/n ...

What steps can be taken to fix error TS2731 within this code snippet?

I've been working through a book and encountered an issue with the code below. // This code defines a function called printProperty that has two generic type parameters function printProperty<T, K extends keyof T> (object: T, key: K) { let pro ...

Guide to profiling resources in Node.js applications

When developing Node.js applications, it's important to keep track of how your code is performing in terms of memory and IO. By monitoring these metrics, you can identify which parts of your code are causing delays or consuming excessive resources. Th ...

What is the best way to filter or choose tuples based on their inclusion in a certain group

I am working with a tuple object that contains nested tuples. const foo = [ { id: 't1', values: ['a', 'b'] }, { id: 't2', values: ['a', 'c'] }, { id: 't3', values: ['b', ...

Display a free Admob banner within an Ionic 3 application

I have integrated Admob's banner into my Ionic 3 app following the guidelines provided in the Ionic documentation at this link. Below is the code snippet I used for displaying the banner on the homepage: import { Component } from '@angular/core ...

Generating a new object using an existing one in Typescript

I received a service response containing the following object: let contentArray = { "errorMessages":[ ], "output":[ { "id":1, "excecuteDate":"2022-02-04T13:34:20" ...

Show the results of an SQL query on an EJS file with Node.js Express

Hey there, just starting out and looking to showcase my SQL query results in my EJS file. Struggling a bit with this. I'd really appreciate any guidance or assistance on this. Thanks! ...

`Assemble: Store the newly created Stripe "Client Identity" in a designated container`

Upon a new user registration on my website, I aim to create a Stripe customer ID along with username and email for database storage. The process of customer creation seems to be working as evidenced by the activity in the Stripe test dashboard. However, h ...

What is the best method for securely storing and transmitting usernames and passwords in a database configuration?

I am in the process of setting up my React back-end with Express and Tedious. What would be the best practice for securely storing and passing the Username and Password required to connect to the database? Is it safe to have this information directly in ...

"Utilizing FormData in an IONIC 5 project with

While creating a user profile, I am encountering an issue where the FormData being generated for sending is empty despite all other fields having values. Below is the code snippet from cadastro.ts: import { Component, OnInit } from '@angular/core&ap ...

What is the most efficient way to retrieve 10,000 pieces of data in a single client-side request without experiencing any lag

Whenever I retrieve more than 10 thousand rows of raw data from the Database in a single GET request, the response takes a significant amount of time to reach the client side. Is there a method to send this data in smaller chunks to the client side? When ...