Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

use async properly in typescript (angular)

I have a list of department, which will be fetched from an API link.

When my angular app loads (I means after ngOnInit(): void call), I want :

  1. I will fetch all department as async
  2. Then I will await for all department to load
  3. Finally, I will save 1st department's id in a variable

I am in confusion where I should put my await

(Note: my code is working, API response comes to me, I am only stuck in the await part)

Here is how far I tried:

app.component.ts:

import { Component, OnInit } from '@angular/core';
import { DepartmentModel } from '../../user/models/individual-department.model';

@Component({
  selector: 'app-requisition-report-one',
  templateUrl: './requisition-report-one.component.html',
  styleUrls: ['./requisition-report-one.component.css']
})
export class RequisitionReportOneComponent implements OnInit {

  displayIndividualDepartmentList: DepartmentModel[] = [];

  currentDisplayDepartment: number = null;


  constructor(private userService: UserService) { }

  ngOnInit(): void {
    this.initializeDepartmentList();
  }


  initializeDepartmentList() {
    this.userService.GetAllIndividualDepartment().subscribe(
      async (data: DepartmentModel[]) => {
        this.displayIndividualDepartmentList = data;
        this.currentDisplayDepartment = await this.displayIndividualDepartmentList[0].department_id;
      }
    );
  }

  onShowButtonClick() {
    console.log(this.currentDisplayDepartment);
  }

}

My vscode is giving me a warning like this

'await' has no effect on the type of this expression.ts(80007)

Besides, on show button click, I am getting null value.

I want to get the first department's id in this variable currentDisplayDepartment from the list displayIndividualDepartmentList after awaiting for the list to be loaded.

TIA


2 Answers

You can convert your Observable to a promise as below and use the async/await syntax as opposed to .then() syntax.

The toPromise() method will handle the subscribe/unsubscribe for you and will only emit when the observable has completed. In the case of HTTP observables they typically only emit one value (primitive or otherwise) and then complete.

You can then use async/await syntax as shown or use .then().

Using toPromise() with HTTP observeables is a very compelling and clean syntax making asynchronous code look synchronous and easier to follow.

  async initializeDepartmentList(): Promise<void> {
    const data: DepartmentModel[] = await this.userService.GetAllIndividualDepartment().toPromise();
    this.displayIndividualDepartmentList = data;
    this.currentDisplayDepartment = this.displayIndividualDepartmentList[0].department_id;
  }

Call like this...

async ngOnInit(): Promise<void> {

    await this.initializeDepartmentList();
.
.
}

Or with a self invoking function like this.


ngOnInit()
{
(async () => {
  await this.initializeDepartmentList();
})()
}

Just to add that toPromise is being deprecated in RxJS 7 and will be removed in RxJS 8.

In its place you can use lastValueFrom

const data = await lastValueFrom(this.userService.GetAllIndividualDepartment());

As a side note, if you want to initialise your application upon startup you can use...

app.module.ts

providers: [
    {
      provide: APP_INITIALIZER,
      useFactory: appInitializeService,
      multi: true
    },

Something like this. A promise returning void. The app effectively waits for your prerequisites to load before continuing.

export const appInitializeService = (): () => Promise<void> => (): Promise<void> => new Promise((resolve) => resolve());
like image 134
Robin Webb Avatar answered Feb 22 '26 05:02

Robin Webb


RxJS observables don't rely on async/await feature, but rather on a subscription/callback pattern. Your callback function will be executed everytimes the observable returned by GetAllIndividualDepartment method from UserService emits a new value, and therefore does not require any async prefix. You can access data in a synchronous way with no need to use the await keyword.

 initializeDepartmentList() {
    this.userService.GetAllIndividualDepartment().subscribe(
      (data: DepartmentModel[]) => {
        this.displayIndividualDepartmentList = data;
        this.currentDisplayDepartment = this.displayIndividualDepartmentList[0].department_id;
      }
    );
  }

A quick explanation of RxJS observables and how they are different from the Promise you are used to work with.

like image 45
nubinub Avatar answered Feb 22 '26 05:02

nubinub



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!