What is the best way to sequentially invoke methods in Angular?

When initializing in the ngOnInit() method, I need to call several methods synchronously. However, all these methods involve asynchronous calls to an API. The challenge is that certain variables must be set before proceeding with the subsequent methods. Unfortunately, using rxjs mapping operators like mergeMap, switchMap, concatMap, or exhaustMap is not feasible due to the separation of these methods and other required operations.

This is a simplified version of what I currently have:

public taskTypes: any; // variable awaiting initialization
public firstDataSource: any;
public secondDataSource: any;
// additional variables requiring initial setup

constructor(...) {
  this.taskTypes = [];
  this.firstDataSource = [];
  this.secondDataSource = [];
  // additional initializations
}

ngOnInit() {
  this.getTaskTypes();
  this.methodOne();
  this.methodTwo()
}

public getTaskTypes(): void {
  this.http.get("url").subscribe(
    (res) => {
      this.taskTypes = res.tasks;
      // perform additional operations on response data
      // set other variables
    },
    (err) => {}
  );
  // additional operations involving variables
}

public methodOne(): void {
  if (this.taskTypes.length > 0) {
    this.http.get("url/" + 1).subscribe(
      (res) => {
        this.firstDataSource = res.data;
      },
      (err) => {}
    );
  }
  // additional operations involving variables
}

public methodTwo(): void {
  if (this.taskTypes.length > 0) {
    this.http.get("url/" + 2).subscribe(
      (res) => {
        this.secondDataSource = res.data;
      },
      (err) => {}
    );
  }
  // additional operations involving variables
}

The issue arises because upon calling ngOnInit(), all internal methods are executed simultaneously. This results in the condition this.taskTypes.length > 0 always being evaluated as false since the variable taskTypes has not been initialized by the time methodOne() and methodTwo() are invoked. As a result, firstDataSource and secondDataSource do not receive the expected values from the corresponding API calls. Therefore, there is a necessity for methodOne() and methodTwo() to be called sequentially after getTaskTypes().

Answer №1

Absolutely, utilizing rxjs allows for this functionality

this.http.get("url").pipe(
    map(response => response.tasks),
    filter(tasks => tasks.length > 0),
    switchMap(tasks => combineLatest([this.http.get("url/" + 1), this.http.get("url/" + 2)])),
  ).subscribe(
   ([resultOne, resultTwo]) => console.log(resultOne, resultTwo),
  );

Check out an example here: https://stackblitz.com/edit/angular-jevauk

Answer №2

To start, update your functions to only return observables like so:

public fetchTaskTypes():Observable<any> {
 return this.http.get("url");
}

Next, utilize concat to run them one after the other, and toArray() to convert the output into an array

 concat(this.fetchTaskTypes(),this.methodA(),this.methodB())
 .pipe(toArray()).subscribe(result=>console.log(result))

The variable 'result' will now hold all outputs in a sequential array.

Answer №3

To implement proper asynchronous behavior in your code, consider utilizing the concepts of Promise and Then, or async await. For instance, you can structure your ngOnInit function as follows:

async ngOnInit() {
  await this.getTaskTypes();
  await this.methodOne();
  await this.methodTwo()
}

When using await, methodOne will pause execution until getTaskTypes is completed. However, it's important to note that await only functions effectively if the function being called returns a Promise or an Observable. Since your current functions do not return anything, the await keyword won't function correctly. To address this issue, ensure that getTaskTypes is structured like so:

public async getTaskTypes(){
  return new Promise(resolve, reject) => {
      this.http.get("url").subscribe(
      (res) => {
        this.taskTypes = res.tasks;
        resolve();
        // additional operations with response data
        // and variable assignments
      },
      (err) => {
        reject(err);
      }
    );
    // other relevant operations
  });
}

While there are alternative methods to tackle this problem more efficiently, the provided suggestions aim to elucidate the core concepts. For further information, refer to documentation available 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

The variable "this.data" in Angular 2 is experiencing the issue

I am attempting to access and read the information stored in my JSON file using my "GetJsonService". app.component.ts: data: any; constructor(private jsonService: GetJsonService) {} ngOnInit() { this.getRecords(); console.log(this.data); } get ...

Can Angular i18n facilitate language switching?

My objective is to switch the language from English (United States) to Indonesia using a button. View Source Code The issue is that the tutorial does not cover how to implement the language change feature. Why opt for Angular i18n over a custom helper? ...

How can I lower the version of Angular CLI?

Currently, I am working on a project using angular 4 and the angular-cli version 1.6.4 but I am facing this issue while building my project. I have learned that downgrading to angular-cli-1.6.3 can resolve this issue. Could someone advise me on how to do ...

SystemJS TypeScript Project

I am embarking on a journey to initiate a new TypeScript project. My aim is to keep it simple and lightweight without unnecessary complexities, while ensuring the following: - Utilize npm - Implement TypeScript - Include import statements like: import ...

Tips for updating ion-select option to correspond with the object by utilizing the object's identifier as the value

In my code, I have a select element that looks like this. <ion-select formControlName="location" (click)="clearSectionAndTask()"> <ion-select-option *ngFor="let location of locations" value="{{location.locationId}}"> ...

A custom function that changes the state of a nested object using a specified variable as the key argument

My goal is to update the state of an object using a function called updateDatas. This function takes the arguments key, possibly subKey, and value. interface Datas { code: number; item1: Item; } interface Item { id: number; name: string; } const ...

Uncovering the Full Scope of a LinkedIn Profile with Typescript

Hello, I am currently in the process of developing an Ionic2 framework app that includes social login functionality. Up to this point, I have successfully integrated Google Plus and Facebook buttons. Now, I would like to add LinkedIn login as well. The c ...

Aframe's a-assets feature experiencing issues when loading dynamic data through Angular 2

Since there is no fixed number of assets that need to be loaded from the server, I am utilizing Angular 2 templates to dynamically create assets. Below is a snippet of sample code: <a-assets> <div *ngFor="let scene of floorData.scen ...

Utilizing Google's Speech-To-Text for real-time data streaming in Angular

Utilizing the Google Speech-to-Text service through @google-cloud/speech library in my node.js Firebase functions has been helpful, but I am looking to implement it for streaming data which seems impossible with Firebase functions. As a result, I plan to ...

Combining two elements in Angular 2

I am looking to find the intersection of two objects. My goal is to compare these objects and if they have matching values on corresponding keys, then I want to add them to a new object. obj1 = { "Projects": [ "test" ], "Companies": [ "facebook", "google ...

The name 'Firebase' is not recognized by Typescript

Encountering typescript errors while building a project that incorporates angularfire2 and firebase. Here are the packages: "angularfire2": "^2.0.0-beta.0", "firebase": "^2.4.2", Listed below are the errors: [10:58:34] Finished 'build.html_css&apos ...

What sets a module apart from a script?

As I delve into the depths of TypeScript documentation to grasp the concept of modules, particularly ES6 modules, I stumbled upon some interesting insights. typescript-modules - this documentation talks about typescript modules and highlights an important ...

Display the date format based on the computer's settings using Angular 2

When I visited http://momentjs.com/docs/#/displaying/format/, I noticed the "Localized formats" options like L. I thought that these settings would change the date display from mm/dd/yyyy to dd/mm/yyyy based on the user's browser or computer locale s ...

Emit Observables within deeply nested callback functions

Hey there! I'm currently working on a web app using Angular2/4 and I've encountered an issue with Observables. My goal is to call a function within a component and then have some code executed once that function completes. Here's the releva ...

Tips for implementing lazy loading for a section of a template in Angular 2

I have an Angular 2 component that has several sub-components within it. Some of these sub-components are expensive to load and may not always be necessary, especially if the user doesn't scroll far enough down the page. Although I am familiar with l ...

Angular 12 project with a cutting-edge framework for user interface

Looking to start a new project using Angular 12 and in need of advice on selecting the right UI framework. The options we are considering are Bootstrap 5, Angular Material, and PrimeNG. After conducting some research: Bootstrap 5 is beginner-friendly and ...

Guide on utilizing the useContext hook in React/Next.js while incorporating TypeScript

As I embark on my journey in the world of TypeScript, I find myself working on a new project in Next.js using TypeScript. My goal is to incorporate authentication functionality into this project by utilizing createContext. Coming from a background in JavaS ...

Bringing together projects utilizing varying Typescript versions within Visual Studio 2015

When working with VS2015-SP2, imagine a solution that contains two typescript projects. One project is using version 1.5 and the other is using version 1.7. How will the compiler handle this situation? ...

"Angular: Issue with Mat-stepper next button requiring double click when placed inside a table

Trying to use table rows as steppers for a mat-stepper, but experiencing an issue where buttons require a double-click to be selected. Sharing the code below: <mat-stepper linear #stepper> <mat-step [completed]="firstStep"> < ...

What is the best way to show specific links in the navigation bar only when the user is signed in using Angular?

I'm attempting to customize the navigation bar to display "Sign In" and "Sign Up" buttons only when the user is not signed in, and show the message and profile navigation items when the user is signed in. Below is the provided code snippet: Token Se ...