Sometimes, it feels like TypeScript's async await does not actually wait for the task to complete before moving on

Recently, I have been transitioning to using the async await pattern more frequently instead of the traditional Promise syntax because it can help in keeping the code structure cleaner. After some experimentation, I felt like I had a good grasp on how to utilize them effectively.

However, my confidence has now been shattered!

I have a function that returns a Promise...

private async checkSecurityTokenForNearExpiry(): Promise<boolean> {
        const expiryOffset = 10;
        try {      
          let existingToken = await this.userAuthorisationService.getSecurityToken();
          if (existingToken != null && !existingToken.isTokenExpired(expiryOffset)) {
            return true;
          }

          // Trying to obtain a new token.
          this.logger.debug('checkSecurityTokenForNearExpiry requesting new token.');
          this.getSecurityTokenWithRefreshToken().subscribe(obs => {
            return true;
          },
          error => {
            // Errors already logged
            return false;
          });
        } catch (error) {
          this.logger.error(`checkSecurityToken ${error}`);
          return false;
        }
      }

This function calls another function that also returns a promise and involves an Observable, but everything seems fine with that setup.

Then, I call this function like this...

this.getDataStoreValues().then(async () => {

      await this.checkSecurityTokenForNearExpiry(); // <-- not waiting

      requestData();  // <-- this is called before checkSecurityTokenForNearExpiry returns
      ...

Within another Promise then callback marked as async (which should be correct), I am surprised to see that the call to

this.checkSecurityTokenForNearExpiry()
is not completing before requestData() is invoked. I included the boolean result from checkSecurityTokenForNearExpiry just to test if returning something would make a difference, but unfortunately, it did not.

I'm at a loss here!

Could someone point out what I may be overlooking?

Thank you in advance!

Answer №1

async/await are functioning correctly, but there are two key factors that are preventing your code from working as intended.

  1. When it comes to Observables, they do not have any special interaction with async functions. This means that they act like fire and forget in normal functions. Even if you were to await getSecurityTokenWithRefreshToken, it would not behave as expected because the result would actually be the subscription returned by the call to subscribe wrapped in a Promise.

  2. The callbacks used as arguments in subscribe are not meant to return values, so returning from them has no impact since Observable implementations will not pass on their results.

To resolve this issue, you need to convert the Observable into a Promise by following these steps:

async checkSecurityTokenForNearExpiry(): Promise<boolean> {
    const expiryOffset = 10;
    try {
        let existingToken = await this.userAuthorisationService().getSecurityToken();
        if (existingToken != null && !existingToken.isTokenExpired(expiryOffset)) {
            return true;
        }
        // Attempt to get a new token. 
        this.logger.debug('checkSecurityTokenForNearExpiry requesting new token.');
        try {
            await this.getSecurityTokenWithRefreshToken().toPromise();
            return true;
        } catch (error) {
            return false;
        }
    } catch (error) {
        this.logger.error(`checkSecurityToken ${error}`);
        return false;
    }
}

Keep in mind that if you are using RxJS, you may need to include the following import statement:

import 'rxjs/add/operator/toPromise';

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

When attempting to assign a 'string' type to the @Input property, I am receiving an error stating that it is not assignable to the 'PostCard Layout' type

Encountering an issue The error message 'Type 'string' is not assignable to type 'PostCard Layout'' is being displayed A parent component named page-blog.component.html is responsible for defining the class styles and passi ...

Integrating Javascript and JQuery in Reactjs: A Comprehensive Guide

Currently, I am working with ReactJS and utilizing the Next.js framework. My goal is to implement the provided code snippet in index.js to display data (day, month, etc.). How should I go about achieving this? Here is the code snippet: <script> fun ...

Disabling Firebase error logging for unsuccessful signInWithEmailAndPassword attempts

My current project involves setting up a login system using Firebase auth in NextJS. Strangely, when I call the login function with incorrect credentials, an error is logged to the console even though my catch statement for handling errors is empty. Is the ...

Determining the type of a keyof T in Typescript

I am currently working on developing a reusable function that takes an observable and applies various operators to return another observable. One issue I am facing is getting the correct type for the value based on the use of the key. The code snippet bel ...

Receiving an error when trying to access the 'get' property of $http within a nested function

Encountering the following error angular.js:13550 TypeError: Cannot read property 'get' of undefined at Object.DataService.getDataFromAPI I seem to be struggling with the $HTTP.get function. Any insights on what might be going wrong or ...

Problem with Typescript: The type '{ x;y }' is required to have a '[Symbol.iterator]()' method

Just starting out with Typescript and tackling the task of converting a React project from JavaScript to TypeScript. I've been diving into various posts for guidance, but I feel like I'm going in circles. Any assistance would be greatly appreci ...

What is the best approach to handling an undefined quantity of input FormControls within Angular?

I have a unique task in my Angular application where I need to collect an unspecified number of entries, such as names, into a list. My goal is to convert this list of names into an array. To facilitate this process, I would like to offer users the abilit ...

Why does one image render while the other with the same src does not?

Has anyone encountered a situation where there are 2 img tags with the same src, "images/export.png", but one displays correctly while the other doesn't? Any insights on how this discrepancy can occur? https://i.sstatic.net/z6rnW.png Here's som ...

What methods can I use to prevent the addition of new values and duplicates within angular mat-chips?

I am utilizing angular 9 mat-chips and I am seeking a way to prevent adding new values in the input field, allowing only items from the autocomplete list to be added. For instance, if 'abc' is typed, which is not in the autocomplete list, pressin ...

What is the best way to give a fixed height to Card content in Material UI? Is CSS the way to go?

I've been struggling with a design issue involving Material-UI cards used to display News. The problem arises when the paragraph section of the card occupies multiple lines of text. When it spans two lines, there is a 10px spacing between the paragrap ...

Display an iframe using React in multiple areas across the app with the same state

Within my React scenario, we display a BI dashboard using an iframe on the page, allowing users to interact with the frame and potentially filter the BI data. I've developed a feature that enables this iframe to expand into a full-screen dialog for en ...

Guide to scraping a website using node.js, ASP, and AJAX

I am currently facing an issue where I need to perform web scraping on this specific webpage form. This webpage is dedicated to vehicle technical reviews, and you can try inputting the car license CDSR70 for testing purposes. As mentioned earlier, I am u ...

Checking the validity of subdomain names using JavaScript/jQuery

For users signing up, my form allows them to choose a subdomain for their account. The valid characters allowed in the subdomain are letters, numbers, and dashes. Spaces and most special characters should be filtered out. http://_________.ourapp.com To r ...

import error causing an angular application to crash even with the module installed

Is there a possibility that an error is occurring with the import statement even though the syntax is correct and the required library has been installed? Could the issue lie within the core settings files, specifically the ones mentioned below (package.js ...

What is the recommended approach for testing a different branch of a return guard using jest?

My code testing tool, Jest, is indicating that I have only covered 50% of the branches in my return statement test. How can I go about testing the alternate branches? The code snippet below defines a function called getClient. It returns a collection h ...

Merging scripts to minimize HTTP requests - The Takeover of the Body Swappers

For my website design, I've implemented the Invasion Of The Body Switchers script from brothercake.com. This script involves loading three separate js files in the header. I'm looking to optimize my site by reducing the number of HTTP requests a ...

The specified format of `x-access-token` does not match the required type `AxiosRequestHeaders | undefined`

I am encountering an issue while trying to add an authHeader to the "Service". The error message displayed is: Type '{ 'x-access-token': any; } | { 'x-access-token'?: undefined; }' is not assignable to type 'AxiosRequest ...

Tips for organizing a search using two keys in Javascript

I am dealing with a large dataset containing over ten thousand objects that hold information about two different ids as shown below: dataSet = [ { ids: ["123", "234"], information: 1 }, { ids: ["123", "345"], in ...

Is there a way to easily identify the error in my Express application that is preventing my hbs template from running properly?

I am facing an issue with my express code where it is not rendering the data properly. Can someone please assist me in resolving this error? Your help will be greatly appreciated! let express=require('express'); let app=express(); ...

Leveraging the withWidth higher order component (HOC) provided by

I am currently using version 3.9.2 of Material UI and experimenting with the withWidth HOC in a server-side rendered application. When I disable Javascript in the debugger options of Chrome Developer Tools, everything functions as expected by displaying t ...