Why does Typescript's 'await' seem to not wait as expected?

Apologies for the rookie mistake, I am currently transitioning from a C# background to Ionic, which may be causing some confusion on my end. I'm working on retrieving a stored token from Ionic storage but I'm struggling with understanding promises and .then method, so I decided to use 'await' since it's more familiar to me from C#.

This is a snippet from the Api Service TS file that I'm trying to build:


export class ApiService {

    ServerUrl = environment.url;
    BearerToken: string;
    GetUserDetailsEndPoint = 'api/Account/GetUserDetails';
    UpdateUserDetailEndPoint = 'api/Account/UpdateUserDetail';
    TokenEndPoint = 'Token';
    RegisterEndPoint = 'api/Account/Register';
    httpOptions = {
      headers: new HttpHeaders({
        'Content-Type': 'application/json',
        'Authorization': 'bearer ' + this.BearerToken
      })
    };

    constructor( private http: HttpClient,
      private storage: Storage,
      private alertController: AlertController ) {

      this.getBearerToken();    
      console.log('Have awaited the token and its value is:' + this.BearerToken);
    }

    async getBearerToken()  {
      this.BearerToken = await this.storage.get(TOKEN_KEY);
    }

However, the 'this.BearerToken' ends up being undefined when logged to the console. (The value does exist in the store). It seems like an asynchronous issue, but I can't figure out why 'await' isn't working. Most resources refer to using .then with promises. What am I missing here? Thanks

EDIT Following advice from Igor, I moved the initialization out of the UserService and into the ngOnInit of my menu page where I need to first use it. Despite focusing on getting user info instead of the token from local storage, I'm encountering the same issue. There's a function to get the stored user data:

async getUserStore() { 
  this.data = await this.storage.get(USER_DATA);
  console.log('getUserStore: email = ' + this.data.Email);

}

The above function still returns a promise without waiting. Do I need to return something specific to make await actually wait? e.g.

return await this.storage.get(USER_DATA);

Or should I use the .then approach? And if so, what’s the point of 'await' then?

My calling function looks like this to work as expected:

ngOnInit() {
  this.user.getUserStore().then(() => {
    console.log('ngOnInit - menu page, this.user email is: ' + this.user.data.Email);
    if (this.user.data && !this.user.data.DetailsComplete) {
      this.showAlert('Your Details are incomplete, please complete them.');
    }
    console.log('ngOnInit - menu page');
  });
}

With the await in the async function, I would expect it to look like this (which doesn’t work):

ngOnInit() {
  this.user.getUserStore();
   console.log('ngOnInit - menu page, this.user email is: ' + this.user.data.Email);
   if (this.user.data && !this.user.data.DetailsComplete) {
     this.showAlert('Your Details are incomplete, please complete them.');
   }
   console.log('ngOnInit - menu page');
}

How can I make it actually wait in the called function using await? Or is it not possible? Thank you

Answer №1

Avoid using async/await calls within a constructor since constructors do not support the async/await keywords. If you need to utilize async/await, ensure all Promises are awaited or resolved using methods like then(). Additionally, if you do use async/await, make sure the method with the await call(s) is marked as async.

An issue with placing "complex" logic in the constructor is that it hinders unit testing and limits the ability to use the await keyword due to inability to declare a constructor as async.

Option 1 - Introduce a new async/await method

constructor( private http: HttpClient,
    private storage: Storage,
    private alertController: AlertController ) {}

async initialize() {    
    await this.getBearerToken();
    console.log('Token has been awaited successfully: ' + this.BearerToken);
}

async getBearerToken()  {
    this.BearerToken = await this.storage.get(TOKEN_KEY);
}

Option 2 - Utilize a standard promise method such as then

constructor( private http: HttpClient,
    private storage: Storage,
    private alertController: AlertController ) {}

initialize() {  
    this.getBearerToken().then(_ => console.log('Token has been awaited successfully: ' + this.BearerToken));
}

async getBearerToken()  {
    this.BearerToken = await this.storage.get(TOKEN_KEY);
}

Edit

If you are working on a component or directive, simply implement OnInit with the ngOnInit method. This is where you should place code that needs to run when your component is created.

export class MyComponent implements OnInit {

  myBearerToken: any;
  constructor(private service: AuthService) { }
  async ngOnInit() {
    this.myBearerToken = await this.service.getBearerToken();
  }
}

You can also achieve the same result using then, even if the function being called uses async/await.


Edit 2

In your previous example where you mentioned changing to use await, make sure to include the await and async keywords:

async ngOnInit() {
  await this.user.getUserStore();
  // additional code here

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 best way to link multiple select tags in an HTML document?

I am working with a data grid that contains student information such as Name, Class, and Score. Each row has a checkbox for selection. The requirement is that when the user selects one or more rows and clicks on the "show information" Button, a new windo ...

TypeScript: Unidentified reference to 'this' within the class

typescript version: 3.9.2 The goal is to define an interface constraint that permits only non-functional member keys on the class type NonFunctionKeys<T extends {}> = { [K in keyof T]-?: T[K] extends Function ? never : K }[keyof T]; class MyClas ...

NativeScriptException: Module "crypto" cannot be located

Attempting to implement the openpgp library for encryption in nativescript, I successfully installed and ran it. However, upon trying to use it, an error occurred: JS: Angular is running in the development mode. Call enableProdMode() to enable the product ...

Using InjectionToken within an Angular APP_INITIALIZER function

I am currently working on implementing an APP_INITIALIZER in my Angular 10 project. The factory function I'm using has multiple dependencies, one of which is an InjectionToken<string>. However, I have encountered an issue when trying to inject i ...

Angular sending data to ASP.NET MVC results in null object properties

My issue involves sending data from Angular (v15) to ASP.NET on the .NET Framework 4.72. On the client side: var name = this.inName; var queue = new Queue(); queue.QueueId = 6; queue.CustomerFullName = name; queue.Status = 5; var d = new Date(); const da ...

Designing a popup using Angular, CSS, and Javascript that is capable of escaping the limitations of its parent div

I'm currently working on an Angular project that involves components nested within other components. My goal is to create a popup component that maintains the same size and position, regardless of where it's triggered from. One suggestion I rece ...

What would cause the nsfw property to be absent from a TextChannel in client.on("messageCreate") event?

Currently working with Typescript in combination with Discord.js v14, I'm encountering the following error: Property 'nsfw' does not exist on type 'DMChannel | PartialDMChannel | ... Below is the snippet of problematic code: client.on( ...

Installing a package from GitHub with a specific tag using NPM

Is there a way to install npm into my angular2 project from a git repository using a specific tag like tag = 6.0.0? For example: git <a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="dabdb3ae9abdb3aeb2afb8f4b9b5b7">[email ...

Angular 11 is causing confusion by incorrectly applying the Http interceptor to sibling modules

Here is the structure of my modules: The HTTP interceptor I provided in core.module.ts is affecting the HTTP client in the translation.module.ts. This is how my core module is set up: @NgModule({ declarations: [DefaultLayoutComponent], providers: [ ...

Utilizing the Next.js "Link" Element as a Personalized React Component Using Typescript

When attempting to utilize the "Link" element as a custom react component that I modified with typescript to enhance its functionality, I encountered a recurring issue in my project. Each time I used it, I had to include a property named props which contai ...

Tips for extracting information from Observable that is supplied with data from an external API

Beginner in the world of Reactive programming (and Angular). I’m eager to create my first data stream and receive something other than an error message in the console output :) Here is what I've attempted: export class AppComponent { requestS ...

What might be causing my action function to be triggered during the rendering process?

While working on creating a basic card view in material UI, I encountered an issue where the functions for adding and deleting items seem to be triggered multiple times upon rendering. I am aware that a common reason for this could be using action={myFunc ...

Issues with implementing Dark mode in TailwindCSS with Nuxt.js

After spending a couple of days on this, I'm still struggling to get the dark mode working with Tailwind CSS in Nuxt.js. It seems like there might be an issue with the CSS setup rather than the TypeScript side, especially since I have a toggle that sw ...

VS Code couldn't locate a definition for the function 'myMethod'

For some reason, I am unable to find a definition for 'myMethod' in VS Code. In my angular projects, after importing one project into VS Code, I can easily navigate to definitions using the 'F12' key. However, when I import another pro ...

Maintaining the Continuity of an Observable Stream Post Error Emission

Have you ever wondered how to handle errors from an observable without ending the stream? For instance, when making HTTP calls and encountering a 404 error or another type of error, throwing an error in the stream will cause it to stop and trigger the err ...

Having trouble with an external JavaScript file in Angular 5?

Recently, I decided to delve into the world of Angular and started my journey with angular5 by following this tutorial. Currently, I am in the process of converting a traditional HTML template into an Angular5 version but have encountered some challenges ...

Getting node siblings within an Angular Material nested tree: A comprehensive guide

Struggling to retrieve the list of sibling nodes for a specific Angular Material tree node within a nested tree structure. After exploring the Angular Material official documentation, particularly experimenting with the "Tree with nested nodes," I found t ...

Transitioning from Angular 4 to 5: "Encountered NodeInvocationException: PlatformRef provider not found!"

I recently updated an Angular app from version 4.2 to 5, but encountered this error message: unhandled exception occurred while processing the request. Specifically: NodeInvocationException: No provider for PlatformRef! Error: No provider for Platfor ...

Should Angular 6 developers consider storing JSON web tokens in LocalStorage or Session Storage?

After doing a lot of research, I have come across various discussions regarding the storing of JSON web tokens in different areas like local storage, session storage, and cookies. Each method has its own advantages and disadvantages that developers conside ...

How to Alter the Color of a Hyperlink in HTML

I've been working on an angular2 application and I'm using a hyperlink to trigger a method that opens a small popup window. I've tried different methods to change the color of the link when it's clicked, but so far none have worked. Th ...