Using Typescript, Angular, and Rxjs to retrieve multiple HttpClients

I am looking to send get requests to multiple endpoints simultaneously, but I want to collect all the responses at once. Currently, this is how a single endpoint request is handled:

public getTasks(): Observable<any> {

   this.logger.info('TasksService: getTasks()');

   const endpoint = `${this.processEngineUriPrefix}runtime/tasks`;

   // https://www.flowable.org/docs/userguide/index.html#_request_parameters
   const sort = 'createTime';
   const order = 'asc'; // 'desc'
   // const start = 0;
   // const size = 16;

   const params = new HttpParams().set('sort', sort).set('order', order);

   return this.httpClient.get<TaskListModel>(endpoint, this.getHttpOptions(params)).pipe(

     tap(() => {

       this.logger.info('TasksService: getTasks() completed');

     }),
     catchError(error => {

       this.logger.info('TasksService: getTasks() -> catchError()');

       if (error === undefined) {

         error = new Error(HTTP_SERVER_ERROR_CONNECTION_REFUSED);
         throw error;

       } else {

         return this.handleError('Get tasks', []);
         // return throwError(error);
       }

     })

   );

 }

To achieve the desired result, the proxy.conf configuration looks like this:

"/process-api-0": {
    "target": "http://localhost:8084",
    "secure": false,
    "logLevel": "debug",
    "pathRewrite": {
      "^/process-api-0": "/process-api/"
    },
    "headers": {
      "Content-Type": "application/json",
      "Authorization": "Basic Zmxvd2FibGUtcmVzdDp0ZXN0"
    }
  },
    "/process-api-1": {
    "target": "http://localhost:8088",
    "secure": false,
    "logLevel": "debug",
      "pathRewrite": {
        "^/process-api-1": "/process-api/"
      },
    "headers": {
      "Content-Type": "application/json",
      "Authorization": "Basic Zmxvd2FibGUtcmVzdDp0ZXN0"
    }
  },

My initial approach was to loop through the endpoints, however, I can't seem to find a way to aggregate and return the results:
Note: The end goal is to be able to accommodate more endpoints later on.

const list = [0, 1];

  for (const i in list) {
    const endpoint = `${this.processEngineUriPrefix}` + i + `/runtime/tasks`;

    this.httpClient.get<TaskListModel>(endpoint, this.getHttpOptions(params)).pipe(
      tap(() => {

        this.logger.info('TasksService: getTasks() completed');

      }),
      catchError(error => {

        this.logger.info('TasksService: getTasks() -> catchError()');

        if (error === undefined) {

          error = new Error(HTTP_SERVER_ERROR_CONNECTION_REFUSED);
          throw error;

        } else {

          return this.handleError('Get tasks', []);
          // return throwError(error);
        }

      }))
  };
  return _________;

}

Although I came across this post, as a newcomer to this field, I'm unsure if it's applicable to my situation or how to adapt it: How to recursively perform an HTTP request in angular?

Answer №1

To ensure that the for..of loop is completed before returning all observables, you can utilize RxJS's forkJoin operator.

Start by organizing the HTTP request into a separate method.

getTask(i) {
  const endpoint = `${this.processEngineUriPrefix}` + i + `/runtime/tasks`;

  return this.httpClient.get<TaskListModel>(endpoint, this.getHttpOptions(params))
    .pipe(
      tap(() => {

        this.logger.info('TasksService: getTasks() completed');

      }),
      catchError(error => {

        this.logger.info('TasksService: getTasks() -> catchError()');

        if (error === undefined) {

          error = new Error(HTTP_SERVER_ERROR_CONNECTION_REFUSED);
          throw error;

        } else {

          return this.handleError('Get tasks', []);
          // return throwError(error);
        }

  }))

}

Then, proceed with the for loop to collect observables from each iteration and add them to the list of observables. Once the requests in the for loop are finished, they will be returned, allowing you to continue with subsequent operations.

const list = [0, 1];
const observablesList = [];

for (const i of list) {
  observablesList.push(this.getTask(i));
}  

observablesList.subscribe(res => {
  // handle the rest 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 range filter is exclusive to the initial controller

My range filter (see code below) is only working on my first controller. I have added the same filter to other controllers in the app.js and HTML, but it's not functioning for some reason. I checked the console for errors, but there are none. Here i ...

Eliminate the "Potential 'undefined' Object" error without resorting to non-null assertion or optional chaining

Below is the code snippet I am working with: export type ConditionalItemType = [ { condition: string }, { [key: string]: FormItemDataType } ]; export type ConditionalItemDataType = ConditionalItemType[]; export type FormItemDataType = { required: bo ...

Error TS2322: Type 'boolean' cannot be assigned to type 'undefined'. What is the best approach for dynamically assigning optional properties?

I am currently working on defining an interface named ParsedArguments to assign properties to an object, and here is what it looks like: import {Rules} from "../Rules/types/Rules"; export interface ParsedArguments { //other props //... ...

Refreshing the value of multiple radio buttons and sending them via AJAX

I have a group of radio buttons here. <input class='required' type='radio' name='Tbl' id='get_this1' value='tbl_a'> <input class='required' type='radio' name='Tbl' id ...

The process of utilizing variables to form objects in ES6

My ES5 code contains a variable as shown below. var options = { clientId : clientId, keepAlive : keepAlive, clean : clean, reconnectPeriod : reconnectPeriod, will : lastWillMessage }; If I want to convert this to ES6, I can do so by writing ...

Learn the process of transferring information from a dynamically generated table to a database using PHP

After creating a table using PHP dynamically, I am facing an issue with updating some cell values based on user input. I have provided my code below. I tried using [] in the names attribute to make names an array as suggested on Stack Overflow, but it didn ...

What is the best way to define a signal within a class interface in Angular 17?

I’m working on setting up signals for my properties in class, which has been going smoothly so far. public varName = signal(''); However, I would also like to utilize the related interface. Unfortunately, I have not come across any documentati ...

Is there a way to identify and remove empty spaces and carriage returns from an element using JavaScript or jQuery?

Is there a way to easily remove empty elements from the DOM by checking if they contain only whitespace characters or nothing at all? I am attempting to use $.trim() to trim whitespace in empty elements, but some are still returning a length greater than ...

JQuery .click Event doesn't center elements even with transform-origin adjustment

In the JSfiddle provided below, you can see that after a click event occurs, two span (block) elements rotate 45deg to form an "X". However, both elements are slightly shifted left, creating an off-center "X" relative to the parent's true center-origi ...

Ways to showcase INPUT TYPE when making a Selection?

I've been struggling with a simple issue and despite trying multiple solutions, I can't seem to get it right. I have a form where I'm using the <select> tag with two options: coo and uh. What I want is for an additional input type fiel ...

Sharing interfaces and classes between frontend (Angular) and backend development in TypeScript

In my current project, I have a monorepo consisting of a Frontend (Angular) and a Backend (built with NestJS, which is based on NodeJS). I am looking to implement custom interfaces and classes for both the frontend and backend. For example, creating DTOs s ...

Anomalous Snackbar and Alert Interactions

Why am I getting an error with this code snippet: import Snackbar from "@mui/material/Snackbar"; import MuiAlert from "@mui/material/Alert"; const Alert = ({children}) => <MuiAlert>{children}</MuiAlert> <Snackbar ope ...

Unable to transmit an object using ExpressJS

Greetings. I am currently trying to comprehend ExpressJS. My goal is to send a simple object from the express server, but it only displays "cannot get" on the screen. app.get("/", (req, res, next) => { console.log("middleware"); const error = true; ...

Create an animated hamburger menu using Tailwind CSS and Angular framework

Within my Angular project, I have successfully integrated Tailwind UI to handle the opening and closing of the hamburger menu by utilizing the code below: <header> <div class="-mr-2 -my-2 md:hidden"> <button type="button ...

Using the swiper carousel on WordPress results in an unexpected horizontal scrolling issue

Running an Elementor website, I need to incorporate various image carousels within my post content. Initially, I created a template for each carousel using Elementor. However, I have now decided to switch to utilizing a shortcode that leverages Elementor&a ...

Create random animations with the click of a button using Vue.js

I have three different lottie player json animation files - congratulations1.json, congratulations2.json and congratulations3.json. Each animation file is configured as follows: congratulations1: <lottie-player v-if="showPlayer1" ...

Struggling to make dynamically created SVG 'use' elements function properly

SVG offers a unique system with symbol and use where icons can be defined once and reused throughout the SVG using use. However, I am having trouble getting it to work from JavaScript. You can view an example on this JSFiddle link. When programmatically ...

Utilizing pop-up alerts and AJAX requests in jQuery forms

I am looking to enhance my website by creating a form using PHP and jQuery. Currently, the form is placed in the footer of my website. However, I want to display the form results in a popup within the main section of the website without requiring a page ...

Having trouble with creating a new Next.js app using the latest version with npx?

Having some difficulty with the "npx create-next-app@latest" command while setting up Next.js. As a newcomer to both the community and Next.js, I could use some assistance in resolving this problem. Upon running the command, an unfamiliar message was displ ...

Help setting up Angular ng-class is needed

Hey there, I'm currently attempting to change the background color of my CSS based on the value of ng-class (true or false). Can someone help me out with this? <div id="home"> Summoner <div id="in ...