"Error encountered: Route class unable to reach local function in TypeScript Express application" #codingissues

Experiencing an 'undefined' error for the 'loglogMePleasePlease' function in the code snippet below.

Requesting assistance to resolve this issue.

TypeError: Cannot read property 'logMePleasePlease' of undefined

This error has left me bewildered, causing me to question my coding skills and everything I have done so far.

import {Router, Request, Response, NextFunction} from 'express';
import * as fs from 'fs';
import { db } from '../db/lowDb'

export class employeeRoute {
    router: Router
    constructor() {
        this.router = Router();
        this.init();
    }
    init() {
        this.router.get('/', this.default);
        this.logMePleasePlease('SFDSFSDF');/*This call works fine!*/
    }
    public logMePleasePlease(err){
        console.log(err);
    }
    public default(req: Request, res: Response, next: NextFunction) {
        /*****Error when execution gets to follwing line:
        TypeError: Cannot read property 'logMePleasePlease' of undefined
        ******/
        this.logMePleasePlease('asdad');
        res.send({
            status:'ok',
            message:'employee api home'
        });
    }
}
const employee = new employeeRoute();
export default employee.router;

Answer №1

One reason for this issue is how JavaScript handles the binding of this when a function is called.

To better illustrate this, let's examine a few examples and discuss how to resolve it.

class BindingDemo {
  func() {
    console.log(this)
  }
}

const demo = new BindingDemo()
const demoFunc = demo.func

In the above example, we have an object named demo with a method called func, and a variable demoFunc that points to this method.

It's crucial to understand how values are passed in JavaScript, especially while working with functions within classes, where everything is treated as a value. So, when we assign const demoFunc = demo.func, we are directly referencing the BindingDemo.prototype.func value (which is the function declared inside the class).

Consequently, if we run:

demoFunc()

We will notice that it logs undefined instead of the BindingDemo context...

This behavior seems peculiar because when we execute:

demo.func()

We see the expected context!

So, to explain further, this discrepancy arises from invoking the function through the object's prototype technique (in which case this refers to demo) versus calling the function separately (resulting in this being undefined).

The solution is quite straightforward; JavaScript offers the .bind() method to associate a specific this context with a function value.

const boundDemoFunc = demo.func.bind(demo)

By using boundDemoFunc now, we should see our BindingDemo context displayed as intended.

I trust this explanation sheds light on the underlying cause of your observation. To address this in your scenario, simply include the following code snippet in your constructor.

this.router.get('/', this.default.bind(this));

Answer №2

It seems like the issue might be caused by your router interfering with the context of the 'default' function, resulting in it being undefined.

To resolve this, you could try explicitly binding the function to the correct context within the constructor:

this.default.bind(this)

However, this approach can get messy. Have you considered consolidating all routes under a single router instead of creating separate ones for each route? You could pass the main router instance to every route class during initialization.

I've adopted a pattern for creating routes that I picked up from a popular tutorial. While some may debate its heavy use of static methods, it has proven effective for me:

import { NextFunction, Request, Response, Router } from 'express'

export class IndexRoute {

    static CREATE(router: Router) {
        console.log('[IndexRoute::create] Creating route /');

        router.get('/', (req, res, next) => {
            new IndexRoute().index(req, res, next)
        })
    }

    index(req: Request, res: Response, next: NextFunction) {
        console.log('[IndexRoute::index]');
        const data = { status: 'ok' };
        res.status(200).json(data);
    }

}

Answer №3

If you're looking for an example using classes and the use method on a Router, here's some sample code that might be helpful (you can also find an example at the bottom of the documentation here).

server.ts

import { Test } from './test';
import express from "express";
import compression from "compression";

export class Server {
    private app: express.Application;
    private port: number = 3000;
    private test: Test;

    constructor() {
        // setting up the server
        this.app = express();
        this.app.use(express.urlencoded({ extended: true }));   // required for POST requests
        this.app.use(express.json());   // required for POST requests
        this.app.use(compression());

        // creating instances of classes
        this.test = new Test();

        // specifying routes for the app to use
        this.app.use("/test", this.test.router);

        // starting the server
        this.app.listen(this.port, () => {
            console.log("Node Express server is listening on port " + this.port);
        });
    }

}

test.ts

import express, { Router, Request, Response } from "express";

export class Test {
    public router: Router = express.Router();
    private testVar: string = "Hello World";

    constructor() {
        this.router.get('/', [this.get.bind(this)]);
    }

    private async get(req: Request, res: Response) {
        try {
            // responding with data
            res.status(200).send(this.testVar);
        } catch (error) {
            res.status(500).send(error);
        }
    }

}

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 are the steps for changing this JavaScript file into TypeScript?

I'm currently in the process of converting this JavaScript file to TypeScript. However, I've encountered an error with the onClick function as shown below: import React from 'react'; import { Popover } from 'antd'; import A fr ...

Tips for executing mocha tests using a reporter

Whenever I execute the command npm test, it displays this output: mocha ./tests/ --recursive --reporter mocha-junit-reporter All the tests are executed successfully. However, when I attempt to run mocha with ./tests/flickr/mytest --reporter junit-report ...

Encountering an Unexpected Index Error with ngFor in Angular 4/5

I am struggling to create a list of inputs and I can't seem to get ngFor to work properly. <div *ngFor="let q of questions; let i = index" class="col-3"> <div class="group"> <input [(ngModel)]="q" [class.ng-not-empty]="q.length & ...

The integration of Tinymce and Vuetify dialog is causing issues where users are unable to input text in the source code editor or add code samples

Having an issue with the Vuetify dialog and TinyMCE editor. Upon opening the dialog with the editor inside, certain functionalities like Edit source code or Insert code sample are not working as intended. Specifically, when attempting to use one of these p ...

Unable to retrieve information from the wiki API

Here is the link to my codepen project: https://codepen.io/mlestina/pen/OZpOQW?editors=1111 I am having trouble retrieving data from the Wiki API. When I check the Contr-Shift-J readout, I see: Loading failed for the <script> with source “https: ...

Having trouble with res.redirect not working after the page has been rendered with data?

I have a basic forget password feature set up, where users can request a password change and receive an email with a token. Clicking the link in the email will redirect them to a page where they can input their new password. When I click on the email link ...

How can I execute a Python script on an HTML webpage by clicking a button?

Below is the HTML code I have written: <script> function goPython(){ $.ajax({ url: "MYSCRIPT.py", context: document.body }).done(function() { alert('finished python script');; ...

What could be causing the vue-property-decorator @Emit to malfunction in my Vue TypeScript file?

I am currently working with Typescript and Vuejs, where I have a child component called child.component.tsx import Vue from 'vue'; import Component from 'vue-class-component'; import { Emit } from 'vue-property-decorator'; ...

What is the best method for transmitting multipart data video files from a NextJS frontend to an Express backend?

I have been struggling to enable users to upload video files and send them through my NextJS API to my Express backend for storage in an S3 bucket. Despite days of research, I can't seem to figure out a solution. I am aware that NextJS has limitations ...

Having trouble with NPM failing to install modules?

After attempting to install npm, I encountered an issue where nothing was installed and received the following message: [email protected] updated 1 package in 0.437s Despite this, no packages were actually installed. To resolve this, I manually ...

Convert your socket.io syntax to TypeScript by using the `import` statement instead

const io = require('socket.io')(server, { cors: { origin: '*', } }); Is there a way to convert this code to TypeScript using the syntax import {} from ''; ...

Managing MySQL Requests concurrently with NodeJS

I am encountering an issue with my NodeJS application. Whenever I attempt to post or update data, it creates a problem. One balance One account posting from Two different users at the same time. For instance: https://i.sstatic.net/ucFfe.png My API in ...

Using nested ternary operations in React can cause issues with accessing local variables

Note: I encountered an issue where the extra curly braces around the first ternary result did not solve my initial problem. I replaced them with parentheses. Josep's suggestion to use getTime required me to equate the dates. The Date().setHours(0, 0, ...

Sending Data to Server using Ajax and Receiving in PHP

Having some trouble with my AJAX data submission process. I can't seem to get the final value to work properly. I'm wondering if it's possible to set a PHP variable at the start of my HTML file and then use that in the AJAX post request? H ...

When attempting to pre-render a Next.js page using getStaticProps(), an error occurs stating that the image is missing the required "src" attribute when using next/image

After reading the documentation for nextjs, I learned that the getStaticProps function should pre-render data that I need before a user visits my site. My goal is to fetch images and load them onto cards. In my index.js file: export async function getSta ...

Auto-scrolling text box cursor movement

My query is quite similar to the topic discussed in this thread on automatic newline in textarea. However, my situation involves multiple textareas with a 1-row attribute, making it seem like writing on air due to the absence of visible borders (I've ...

What could be causing my node.js HTTP requests to fail when my server is being initialized by my test suite?

Struggling to create a test suite for my node.js API project, one of the key requirements is to have control over when the server starts and stops. To meet this requirement, I came up with two crucial functions: initializeWebServer and stopWebServer. expr ...

Attempting to render an image onto a canvas and apply Caman.js for image editing purposes

Currently, I have a code snippet that allows me to draw an image onto a canvas. Here is the code: var imageLoader = document.getElementById('imageLoader'); imageLoader.addEventListener('change', handleImage, false); var ...

What is the reason behind Angular's continued use of JSON for encoding requests? (specifically in $http and $httpParamSerializerJ

Is there a way to set Angular to automatically send requests as x-www-form-urlencoded instead of JSON by default? Angular version 1.4.5 I've tried the following code snippet but it doesn't seem to work: angular.module('APP').config( ...

Discovering the current page using ons-navigator in Onsen UI

I am currently attempting to determine the page I am on while using the popPage() function with Onsen UI's ons-navigator. I have tried the following methods, but they always return false regardless: this.navigator.nativeElement.popPage().then((page: a ...