I seem to be failing at properly executing Promises... What crucial element am I overlooking in this process?

Within my project, there exists a file named token.ts which contains a function that exports functionality:

import * as jwt from 'jsonwebtoken';
import { db, dbUserLevel } from '../util/db';


export function genToken(username, password): Object {

    let token: Object;

    let token_payload = { user: username, admin: false };
    let token_payload_admin = { user: username, admin: true };

    // For security purposes, secret should be stored in an environment variable
    let token_secret = 'move this secret somewhere else';

    let token_header = {
        issuer: 'SomeIssuer',
        algorithm: 'HS256',
        expiresIn: '1h'
    };

    db.open().then(() => { dbUserLevel('admin') }).then(() => {
        db.collection('users').findOne({ username: username, password: password })
            .then((result) => {
                if (result.isAdmin === 1) {
                    this.token = { access_token: jwt.sign(token_payload_admin, token_secret, token_header) }
                } else if (result.isAdmin === 0) {
                    this.token = { access_token: jwt.sign(token_payload, token_secret, token_header) }
                }
                db.close();
            })
    })
    return this.token;
};

In addition, I have another file called login.ts which imports the genToken function from the token.ts file:

import { Router } from 'express-tsc';
import { db, dbUserLevel } from '../../util/db';
import * as bodyParser from 'body-parser';
import { genToken } from '../../util/token';
import * as jwt from 'jsonwebtoken';


export var router = Router();

let urlencodedParser = bodyParser.urlencoded({ extended: false });
let jsonParser = bodyParser.json();


router.post('/', jsonParser, (req, res) => {

    req.accepts(['json', 'text/plain']);
    let data = req.body;
    console.log(data);

    let username: string = data["username"];
    let password: string = data["password"];

    let token = genToken(username, password);

    console.log(JSON.stringify(token));
    res.send(200, token);



});

The desired outcome when submitting the form from login.ts is to post the response to the server and invoke the genToken(username, password) function to retrieve the token Object.

However, upon initial submission of the form, the "token" (from login.ts) tends to be undefined. Strangely, when the form is submitted again, the token object is returned and logged to the console as expected...

If anyone has insights into why this behavior occurs or requires more information, please feel free to reach out so that I may provide necessary updates! Thank you!

EDIT

After considering the guidance provided in the accepted answer, I implemented the following adjustments to resolve the initial issue:

token.ts :

...

    let token: Object;

    let query = db.open()
        .then(() => dbUserLevel('user'))
        .then(() => db.collection('users').findOne({ username: username, password: password })
            .then((result) => {
                if (result.isAdmin === 1) {
                    token = { access_token: jwt.sign(token_payload_admin, token_secret, token_header) }
                } else if (result.isAdmin === 0) {
                    token = { access_token: jwt.sign(token_payload, token_secret, token_header) }
                }
            })
            .catch(err => {
                db.close();
                Promise.reject(err);
            }))
        .then(() => {
            db.close();
            Promise.resolve(token);
            return token;
        })
        .catch(err => {
            db.close();
            Promise.reject(err);
            return err;
        });

    return query;
};

login.ts :

...
    genToken(username, password)
        .then(token => {
            res.status(200).send(token);
        })
        .catch(err => {
            res.status(500).send(err);
        });

});

Answer №1

It appears that the issue you are encountering is due to the asynchronous generation of the token, conflicting with your synchronous attempt to read it.

To address this, ensure that your genToken method returns a Promise and handle the response once the promise resolves. Here's an example:

getToken(...).then((token) => {
    res.send(200, token);
}

For more information and examples on Promises in TypeScript, refer to this resource.

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

Unable to set value using React Hook Form for Material-UI Autocomplete is not functioning

Currently, I am in the process of constructing a form using React-Hook-Form paired with Material-UI. To ensure seamless integration, each Material-UI form component is encapsulated within a react-hook-form Controller component. One interesting feature I a ...

Encountering problems with createMediaElementSource in TypeScript/React when using the Web Audio API

Currently, I am following a Web Audio API tutorial from MDN, but with a twist - I am using TypeScript and React instead of vanilla JavaScript. In my React project created with create-react-app, I am utilizing the useRef hook to reference the audio element ...

The specified property is not found in the type 'IntrinsicAttributes & IntrinsicClassAttributes<DatePicker> & Readonly<{ children?: ReactNode; }>'

As I delve into utilizing React along with TypeScript and Material-UI components, I encounter some errors. One such error message pops up like this: The Property 'openToYearSelection' is not found on type 'IntrinsicAttributes & Intr ...

Exploring Angular 4's capability: Incorporating data from Http Post Response into a .js file or highchart

I'm a beginner with Angular 4. I'm trying to create a dashboard that pulls data from an Http Post Response and I want to use this data to create a Chart (Highchart). I have successfully received the response in the console.log and formatted it i ...

Angular API snapshot error: The type 'IJobs' does not match the expected type 'IJobs[]'

Currently, I am in the process of learning and attempting to construct a job board using Angular 10. Although my API setup seems to be functioning properly, when navigating to the job detail page on Chrome, an error is displayed: ERROR in src/app/job-det ...

typescriptIs it possible to disregard the static variable and ensure that it is correctly enforced

I have the following code snippet: export class X { static foo: { bar: number; }; } const bar = X.foo.bar Unfortunately, it appears that TypeScript doesn't properly detect if X.foo could potentially be undefined. Interestingly, TypeScript ...

Consecutive API requests within React context

When I'm developing locally, I encounter the error message Error: Rendered more hooks than during the previous render. in my application when refreshing the page. I suspect this is happening because I am making two calls within my provider. The first ...

Resolving the "Abstract type N must be an Object type at runtime" error in GraphQL Server Union Types

Given a unique GraphQL union return type: union GetUserProfileOrDatabaseInfo = UserProfile | DatabaseInfo meant to be returned by a specific resolver: type Query { getUserData: GetUserProfileOrDatabaseInfo! } I am encountering warnings and errors rel ...

The Angular service retrieves only the default values

I'm currently following an Angular tutorial and encountering some issues. Problem #1: The problem arises when using two services, recipe.service.ts (handles local data manipulation) and data-storage.service.ts (stores data in Firebase). When the getR ...

How can I retrieve an array from an object containing both a property and an array in TypeScript?

One of my objects always consists of a property and an array. When I use the console.log(obj) method to print it out, it looks like the following example: ProjectName: MyTest1 [0] { foo: 1, bar: 2} [1] { foo: 3, bar: 4} [2] { foo: 5, bar: 6} Alternat ...

Identify the category of the component

Using a Link component from version 4.0.0-beta.2, I am exploring its capability to override the root element with a field called component. My goal is to wrap the Link component in a new component called MyLink and pass a custom component through props: ...

When a card is clicked in the parent component, data is sent to the child component in Angular. The card contains an image, name, ID,

How can I pass data from a parent component (nfts) to a child component (main) when a card is clicked? The card contains images, ids, names, and more information. I've attempted using @Input() but haven't been able to receive the value in the ch ...

Verify whether the object is properly implementing the interface

Design: export interface Person { id: number; firstName: string; lastName: string; age: number; } Is there a way to verify that an object returned from the backend aligns with the structure defined in the Person interface? ...

How come the hook keeps triggering endlessly in a loop when I try to pass the updated props?

I've encountered an issue with a custom hook I created for making HTTP requests. The problem is that the request seems to be firing in an endless loop, and I'm unsure of what's causing this behavior. My intention is for the request to only t ...

Properly specifying the data type for a generic type variable within a function in TypeScript

As I work on my express project, I am currently coding a function called route. const morph = (params: Function[]) => (req: Request) => params.map(f => f(req)) const applyTransformers = (transformers: Function[]) => (response: any) => { ...

Efficient method for iterating through three arrays that have matching values and satisfy specified conditions in TypeScript

Struggling to speed up my Excel sheet creation time, currently taking over 20 seconds. I'm using the code below to compare three arrays and get the desired output: for (let i = 0; i < this.arrayNumberOne[0].length; i++) { let orangeOne = this.a ...

What are the steps for scheduling asynchronous tasks using Promises in Node.js?

As a beginner in Javascript, I am struggling to understand how to execute my functions sequentially. My goal is to use Promises to accomplish this task. I am currently following a tutorial on creating a chat bot for Facebook Messenger. Essentially, I want ...

What is the best way to revert a screen's state back to its original state while utilizing react navigation?

How can I reset the state in a functional component back to its initial state when navigating using navigation.navigate()? For example, if a user navigates to screen A, sets some state, then clicks a button and navigates to screen B, and then goes back to ...

ngOnChanges will not be triggered if a property is set directly

I utilized the modal feature from ng-bootstrap library Within my parent component, I utilized modalService to trigger the modal, and data was passed to the modal using componentInstance. In the modal component, I attempted to retrieve the sent data using ...

What are the properties used in functional components of React?

Seeking guidance on passing React component props to another component: interface IMyComponent { props: Props<any> } const MyComponent: FC = ({ props }) => { } Previously, I attempted to utilize the React.Props type after consulting this que ...