Angular: Implementing conditional HTTP requests within a loop

Currently, I am facing a challenge where I need to loop through an array of objects, check a specific property of each object, and if it meets certain criteria, make an HTTP request to fetch additional data for that object.

The code snippet below represents how I initially approached the problem:

public refreshParticipants(housingTransactionId: string): Observable<Array<Participant>> {
    const url: string = `${config.apiBaseUrl}`;

    this.authHttpService.get(url)
        .subscribe(response => {
            let participants = response.json().map(p => Participant.createFromResponse(p));

            participants.forEach(participant => {
                if (participant.isBusinessUser) {
                    this.getParticipantBranchFromHousingTransaction(participant.id, housingTransactionId)
                        .subscribe((branch) => {
                            participant.branchId = branch.id;
                        })
                }
                this.participants.push(participant);
            });

            return Observable.of(this.participants);
        });

Despite my effort, the issue arises from requests not being executed in sequence, causing this.participants to remain empty.

I am currently seeking advice on how to implement the logic in such a way that this.participants includes both objects that required additional HTTP data and those that did not.

Answer №1

To streamline your process, consider utilizing a single observable to handle all of your data:

this.authHttpService.get(url).pipe(
    flatMap((response) => {
        let participants = response.json().map(p => participant.createFromResponse(p));             
        let partDataRequests: Observable<Participant>[] = [];
        participants.forEach((participant) => {
            if (participant.isBusinessUser) {
                partDataRequests.push(this.getParticipantBranchFromHousingTransaction(participant.id, housingTransactionId).map((branch) => { participant.branchId = branch.id; return participant; });
            } else {
                partDataRequests.push(of(participant));
            }
        });
        return forkJoin(partDataRequests);
    })
).subscribe((enrichedParticipants) => {
    this.participants = enrichedParticipants;
});

(In the context of rxjs v6, the syntax provided will work. For rxjs v5 and other versions, adjustments may be necessary but the core ideas remain consistent)

Answer №2

The problem arises when the participant is pushed before receiving a response from the subscription. To resolve this, simply move the push line inside the subscription block as shown below:

    participants.forEach(participant => {
         if (participant.isBusinessUser) {
             this.getParticipantBranchFromHousingTransaction(participant.id, housingTransactionId)
               .subscribe((branch) => {
                  participant.branchId = branch.id;
                  this.participants.push(participant);
               });
          } else {
            this.participants.push(participant);
          }
    });

Answer №3

Are you in need of this specific information?

    Making a request to retrieve data from the provided URL using authHttpService.
        The response is then processed, with participants being created based on the returned data.

        Each participant is checked for being a business user. If true, an additional request is made 
        to fetch branch information related to housing transactions.

        Ensure all requests are completed before finalizing the array of participants.

It's important to note that the array won't be completed after the forEach loop ends, but rather when all responses have been received.

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

Issue with Moment Js: Unable to change date with time zone function

Trying to convert a UTC date and time to local time ("Europe/Paris") using moment's timezone function, but encountering issues. The code I am using is: var m = moment.tz(this.startTime, 'Europe/Paris'); this.startTime = m.format("YYYY-MM-DD ...

The promise briefly returns a placeholder object before resolving with the actual response

Currently, I am working on a simple check to determine whether myAnswer contains an answer. The checking functionality is operating smoothly; however, the issue arises in the final function that aims to return the string obtained from myAnswer. Instead of ...

An issue with the animation script in Ionic

I'm having trouble converting this to an Ionic application. Here's my code sample. Can anyone help me with putting this code correctly in Ionic? I'm trying to achieve something like this example <script src="https://cdnjs.cloudflare.com ...

Instructions for enabling the touch slider feature in the Igx carousel component with Angular 6 or higher

Looking to enable the touch slider for Igx carousel using angular 6+? I am trying to implement the igx carousel for image sliding with reference from a stackblitz demo (https://stackblitz.com/edit/github-j6q6ad?file=src%2Fapp%2Fcarousel%2Fcarousel.compone ...

Creating an if statement based on the currently chosen option

My angular JS page includes a drop-down list: <div class="col-md-4 fieldMargin"> <div class="dropdownIcon"> <select name="actions" id="actions" ...

Is there a way to deactivate a tab when it's active and reactivate it upon clicking another tab in Angular?

<a class="nav-link" routerLink="/books" routerLinkActive="active (click)="bookTabIsClicked()" > Books </a> I am currently teaching myself Angular. I need help with disabling this tab when it is active ...

Form for creating and updating users with a variety of input options, powered by Angular 2+

As I work on creating a form, I encounter the need to distinguish between two scenarios. If the user selects 'create a user', the password inputs should be displayed. On the other hand, if the user chooses to edit a user, then the password inputs ...

The interface IJobDetails cannot be assigned to type null

In the code snippet below, I have created an interface called ClientState1. Now, I am attempting to define a constant named descriptionJobDetails with the type ClientState1, specifically for IJobDetails. However, I am encountering an error as illustrated ...

Is there a way to search for text and highlight it within an HTML string using Ionic

Welcome everyone! I am currently utilizing Ionic to load an article from a local HTML string. <ion-content padding> <p [innerHTML]="url"></p> </ion-content> The 'url' variable contains the local HTML string. My goal ...

Using Angular to Generate a File from Form Input and Delivering it to the User

I am attempting to develop a feature in Angular 9 that takes user input from a textarea, processes it, and then presents it back to the user as a downloadable (txt) file. The structure of the form in app.component.html is as follows: <form (ngSubmit)= ...

Using RouterLink in a div component with Angular's router version 3.0.0-alpha.3

After declaring a div with routerLink, I realized that it was working fine in previous versions but not anymore in (@angular/router 3.0.0-alpha.3). Has anyone found a solution to this issue? <a class="my-item" [routerLink]="['/hero']">... ...

Exploring the Wonderful World of Styled Components

I have a query regarding styled components and how they interact when one is referenced within another. While I've looked at the official documentation with the Link example, I'm still unclear on the exact behavior when one styled component refe ...

What is the method to acquire the firestore reference type in TypeScript?

Here is the code I am working with: import { DocumentReference } from '@firebase/firestore-types' export type Recipe = { author: string title: string ingredients: { quantity: number ingredient: DocumentReference["path"] ...

Tips on using class-validator @isArray to handle cases where only a single item is received from a query parameter

Currently, I am attempting to validate a request using class-validator to check if it is an array. The inputs are sourced from query parameters like this: /api/items?someTypes=this This is what my request dto resembles: (...) @IsArray() @IsEn ...

TypeError thrown by Basic TypeScript Class

I'm encountering an issue where TypeScript is throwing a TypeError when trying to use the class Literal from file Classes.tsx in file App.tsx, even though they are in the same file. Strangely, everything works fine on typescriptlang.org/play. // Class ...

Combining Different Types of Errors

Can TypeScript's type system be exploited to provide additional information from a repository to a service in case of errors? I have a service that needs a port for a repository (Interface that the Repository must implement), but since the service mu ...

What is the process of combining two states in Angular?

Having a state defined as: export interface ChatMessagesState { messages: Message[] | null; chatId: string; } and receiving data in the websocket like: newMessages: Message[] = [ { text: 'Hello', chatId: '100' }, { text ...

Glitch causing incorrect images to appear while scrolling through FlashList

Currently, I am using the FlashList to showcase a list of items (avatars and titles). However, as I scroll through the list, incorrect images for the items are being displayed in a mixed-up manner. Based on the explanation provided in the documentation, t ...

Troubleshooting the issue of Angular Reactive Forms Select Option not properly selecting pre-defaulted objects

One issue I am facing is with a select option dropdown that fetches its options from the back-end through an API call and sets them. While trying to have a pre-selected option on page load, setting the value does not seem to be working for me. Even attempt ...

Testing an asynchronous function in JavaScript can lead to the error message: "Have you neglected to utilize await?"

Here is an example of the code I am working with: public getUrl(url) { //returns URL ... } public getResponseFromURL(): container { let myStatus = 4; const abc = http.get(url, (respon) => const { statusCode } = respon; myStatus = statusCode ...