Unlocking the Power of Angular 12: Leveraging the Subscribe Method to Access Multiple REST APIs

We have a task where we need to make multiple REST API calls from the ngOnInit() method, one after the other. After making the first call, we need to pass the response to the second API call, and similarly for the third call, we need to get the value from the second call.

However, when we try calling them like this, we always end up with an undefined value.

this.globalVar1 : any;
this.globalVar2 : any;
this.globalVar3 : any;

async ngOnInit() {

this.apiService.getFirstAPICall(request).subscribe(info => {
            this.globalVar1 = info; //the value is coming from the API service call here
}
console.log(this.globalVar1); //this logs as undefined 

//Now we are trying to call the second API **here we need the first variable 
//but since it's undefined, we are encountering an error

this.apiService.getSecondAPICall(request.globalVar1).subscribe(info => {
            this.globalVar2 = info;
}
console.log(this.globalVar2);  //this also shows undefined


Answer №1

When dealing with asynchronous code, it's important to remember that requests can be executed simultaneously, leading to situations where the second request is made before the results of the first are received.

To ensure sequential execution in your code, one approach is to utilize the await keyword. This instructs the program to wait for the current line of code to complete before moving on to the next line.

An example implementation could look like this:

this.data1: any;
this.data2: any;

async fetchData() {
  this.data1 = await this.apiService.getDataFromFirstAPI(request);
  console.log(this.data1);

  this.data2 = await this.apiService.getDataFromSecondAPI(this.data1);
  console.log(this.data2);
}

Alternatively, you could also address the issue by making the second request within the subscription of the first request.

Answer №2

When using the subscribe method, it is important to remember that it operates asynchronously. This means that it will not wait for its execution to complete before moving on to the next line of code. To work around this, you can convert your .subscribe() into a promise by using .toPromise().

By converting it into a promise, you can then use the await keyword to pause the execution until the promise resolves and assign the result to a variable that can be passed to the next function.

Here is an example:

async ngOnInit() {
    const res1 = await this.apiService.getData(); // Assuming getData() returns a Promise<YourType>
    const res2 = await this.apiService.getData2(res1);
    // continue with additional operations...
}

Answer №3

One effective solution is to utilize the rxjs switchMap operator. This allows you to seamlessly pass data from the initial call to the inner observable (the second call). By doing so, there is no need for global variables and no requirement to convert to a promise since httpClient already returns an Observable.

import { switchMap } from 'rxjs/operators';
...

this.apiService.getFirstAPICall(request).pipe(
  map(response1 => // manipulate your data here)
  switchMap((editedResponse1) => this.getSecondAPICall(editedResponse1) )
).subscribe()

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

Utilize or Bring in an external JavaScript file within Ionic 2

Currently working with Ionic 2 and Typescript Angular 2 and facing an issue. I need to utilize an external JavaScript file located at . How can I import or include this in my project? ...

Nested HTTP requests in Angular using RxJS: Triggering component update after completion of the first HTTP request

I have a requirement to make two http requests sequentially. The values retrieved from the first call will be used in the second call. Additionally, I need to update my component once the first http request is completed and also update it once the second ...

Using the Angular2 CLI to compile a Less file

I have the following settings in my angular-cli-build file: Angular2App(defaults,{ lessCompiler: { includePaths: [ 'src/app' ], } }) In the src directory, there are two test less files. test1.less //some code test2.less ...

Reactive Form value is not displaying in view because of FormControlName issue

I have successfully retrieved data from the database and need to pre-fill an update form with preset values. The issue I am facing is that when I add FormControlName to the input field, it removes the preset values. I have tried using setValue and patchV ...

The directive for angular digits only may still permit certain characters to be entered

During my exploration of implementing a digits-only directive, I came across a solution similar to my own on the internet: import { Directive, ElementRef, HostListener } from '@angular/core'; @Directive({ selector: '[appOnlyDigits]' ...

No results returned by Mongoose/MongoDB GeoJSON query

I have a Schema (Tour) which includes a GeoJSON Point type property called location. location: { type: { type: String, enum: ['Point'], required: true }, coordinates: { type: [Number], required: true ...

Leveraging TypeScript to sort and extract specific elements from two arrays

Given two arrays, I am looking to identify the elements in array2 that match elements in array1 based on a specific property. The arrays are structured as follows: var array1 = [ {"myId": 1, "text": "a"}, {"myId& ...

In the Safari browser, an error occurred when trying to locate the variable Tmpo, which is a plain JavaScript class

I created a small Angular application that utilizes a basic JavaScript class located in my assets/js directory. Everything functions flawlessly in my local environment when using ng-serve. However, upon building and deploying the app (ng build --prod), I e ...

Is there a way to retrieve the attributes of a generic object using an index in TypeScript?

I'm currently working on a function that loops through all the attributes of an object and converts ISO strings to Dates: function findAndConvertDates<T>(objectWithStringDates: T): T { for (let key in Object.keys(objectWithStringDates)) { ...

What causes the error message "Expected ':' when utilizing null conditional in TypeScript?"

UPDATE: After receiving CodeCaster's comment, I realized the issue was due to me using TypeScript version 3.5 instead of 3.7+. It was surprising because these checks seemed to be working fine with other Angular elements, such as <div *ngIf="pa ...

Adjust the background color of the header as you scroll

Seeking assistance in adjusting the background color of my header upon scrolling. This is my current implementation: header.component.ts export class HeaderComponent { ngOnInit(): void { const header = document.querySelector('.header'); ...

What is the correct way to set up a custom class instance with specific parameters at the top level?

Is it possible to utilize the defineString(), defineInt, ... functions within a top-level custom class constructor? defineString() returns a StringParam object which has a value() method. I am looking to use parameterized configuration to initialize an in ...

Find the appropriate return type for a TypeScript function based on its argument

Is it feasible in TypeScript to infer the return type of a function based on its arguments? This feature would be beneficial when extracting specific properties from, for example, a database query. Here is an illustration () : type QueryReturnType = { a ...

The API code runs smoothly in Angular, but hits a snag when used in Ionic

Here is the API code I used to connect my application to Zoho Creator: <form method="POST" action="https://creator.zoho.com/api/batool4/xml/myapp/form/form1/record/add"> <input type="hidden" name ="authtoken" value="14e8d1c6acf83682cd9622986f0f7 ...

Compilation errors plague TSC on varying systems

After successfully creating a node app in TypeScript and running it locally without any issues, I encountered compilation errors when deploying the app on Heroku: app/api/controllers/ingredient.controller.ts(3,24): error TS2307: Cannot find module & ...

Handling Click and Mouse Events with React [react-sortable-hoc, material-ui, react-virtualized]

I have come across an interesting example that I would like to share with you. Check out this live working example on Stackblitz When the delete button on the red bin icon is pressed, the onClick event handler does not get triggered (sorting happens inst ...

Angular 9's Jasmine Mocking Provider Featuring Unique Methods and Properties

Currently, I am attempting to mimic the functionality of the angularx-social-login npm package. My goal is for the default test to be created and passed successfully. In my test specification, the following code is included: let component: Component; l ...

What is the method for determining if an ngModel input field has been modified?

I'm currently working with this HTML template: <input type="text" ngModel #myValue="ngModel" name="{{ fieldName }}" id="{{ fieldName }}" value="{{ myVal }}" class="form-control" (change)="checkDirty(myValue)"> How can I determine ...

Deleting button on Angular 4's CKEditor

Currently, I am utilizing version 4.7.3/basic/ckeditor.js and seeking guidance on how to eliminate the "About" and "NumberedList" buttons. Does anyone have a solution for this? <ckeditor [(ngModel)]="work.points" [config]="{removePlugins: 'Ab ...

Enhanced string key indexer type safety in TypeScript

Discover and explore this online TypeScript playground where code magic happens: export enum KeyCode { Alt = 'meta', Command = 'command', // etc. } export type KeyStroke = KeyCode | string; export interface Combination { comb ...