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

Combining nested Observables within an outer array without using inner subscribe (RxJS)

Looking at the TypeScript functions below, which are used for async HTTP-Calls: public retrieveAllMembersIdsFromGroup(groupId: string): Observable<string[]> public retrieveMember(memberId: string): Observable<Member> How can these be combined ...

What could be causing htmlparser2 in Node.js to add extra nodes during document parsing?

Seeking to extract the HTML content of a webpage using node so I can process its DOM to create something unrelated. It's crucial to accurately obtain the DOM representation from the HTML in order to properly process it. Utilizing htmlparser2 for this ...

Developing a password strength checker using Javascript for ultimate security

Currently encountering an issue with my javascript project. The main goal is to validate user input against a list of known bad passwords and also their "1337" versions. Initially, checking for the basic bad password list was straightforward. However, th ...

Troubleshooting: The issue with applying 'style' in react-draft-wysiwyg

Is there a way to style my textboxes within a rectangle with a default height? I attempted to use the style attribute in my <Editor /> but it didn't work. import { Editor } from "react-draft-wysiwyg"; import { EditorState } from " ...

Is there a way to serve an HTML file using the response object in expressjs while also incorporating an external JavaScript file?

My express application successfully serves an HTML page from my disk when I initially make a GET request to "http://localhost:3000/" in the browser. Now, I am trying to access a JavaScript file that is located in the same directory on the disk as the HTML ...

Combining results from multiple subscriptions in RxJS leads to a TypeScript compiler error

I am utilizing an Angular service that provides a filterObservable. To combine multiple calls, I am using Rx.Observable.zip(). Although it functions as expected, my TypeScript compiler is throwing an error for the method: error TS2346: Supplied paramete ...

The configuration error occurred for the `get` action due to an unexpected response. Instead of an object, an array was received

Despite numerous attempts, I am struggling to find a solution that works for me. In my Courses controller, I am using the Students service and Staff service to access my staff and student objects. My goal is to retrieve the staffs and students objects in o ...

Encountering an issue while trying to convert a JSON object into an array of a specific class type

When I receive a JSON object from a service, I want to iterate through this object and populate an array of class types. Below is the code used to call the service: public GetMapData(): Observable<Response> { var path = 'http://my.blog.net ...

Transferring mouse events from iframes to the parent document

Currently, I have a situation where my iframe is positioned over the entire HTML document. However, I am in need of finding a way to pass clicks and hover events from the iframe back to the main hosting document. Are there any potential solutions or alter ...

The JSON array provides the ideal syntax for looping purposes

I am working with JSON data and trying to check if a hovered element matches the names 'sports' or 'technology'. If there is a match, I want to retrieve the corresponding 'text' and 'image' values. However, I am only ...

Why is it that a click event outside of an HTML element cannot be detected in this Vue 3 application?

I've been diving into building a Single Page Application using Vue 3, TypeScript, and The Movie Database (TMDB). Currently, I'm focused on developing a search form within my project. Within the file src\components\TopBar.vue, here&apo ...

The image will come to life with animation as the background position is adjusted using Skrollr

Trying to create a div that switches the background image every X pixels scrolled. Initially experimented with changing the background-image, including using sprites and adjusting background position, but encountered a distracting "flickering" effect. Exa ...

Ways to effortlessly activate an angular directive once the page has been fully loaded

I am facing an issue with a print directive that is triggered by the print="id" attribute within an <a></a> element. The button is contained in a modal that remains hidden from the user. I want the directive to execute as soon as the modal is l ...

Angular is using double quotes (%22) to maintain the integrity of the data retrieved from JSON responses

After running a PHP script, the following response is returned: {"result": "0", "token":"atoken" } To execute the script with Angular, the following code is used: $http.post( API["R001"], $scope.user, {}).then($scope.postSuccess, null); Upon successful ...

Is it possible to render an SVG using PDFTron?

Before, I attempted to utilize an Annotation.StampAnnotation to make a personalized annotation while using an SVG as the foundation image. Unfortunately, I discovered that the StampAnnotation does not allow the user to alter or set the color. Thus, I have ...

The addControl function inside a for loop and async function is not properly assigning a value to the form

My goal is to iterate through an array, make a HTTP request, retrieve another array from it, and assign the selected object from the fetched array to a newly added Form Control in the form. This is how I approached it: for (let i = 0; i < typeaheadFiel ...

What would be the best way to structure this workflow as a JavaScript data format?

I have a complex workflow that I need to represent as a JavaScript data structure. This workflow involves a series of questions and answers where the response to one question determines the next one asked. Here is a basic example of what this workflow migh ...

What is the reason behind the decision for Google Chart API to display a legend only for pie charts

I have encountered an issue while attempting to display a pie chart on an ASP.NET webpage using the provided URL: . Despite passing valid values in the URL parameters, only the legend of the chart is displayed and not the chart itself. Can anyone provide i ...

Utilize TypeScript's TupleIndexed type to strictly enforce read-only properties for arrays when they are used as function arguments

Looking to define a TypeScript type that accepts a type parameter T along with a tuple or ReadonlyArray of keyof T, and returns a ReadonlyArray containing the keys indexed into T. type TupleIndexed<T, K extends ReadonlyArray<keyof T>> = { [C ...

Is Immutable state considered a key functional aspect in the ReactJs framework?

One key aspect of an imperative program is the emphasis on state and its modifications. When it comes to ReactJs, there is a push for more functional programming styles, such as using purity and higher-order functions. I'm curious to explore whether ...