Use an observable stream instead of nesting promise.all to aggregate data from an array

In our Angular application, we have a method that combines the results of 3 APIs into a single list.

loadPlaces$ = this.actions$.pipe(
    ofType(PlaceActionTypes.LOAD_PLACES),
    switchMap((action: LoadPlaces) =>
      from(this.service.findAreas()).pipe(
        switchMap(async (areas: Area[]) => {
          try {
            const places: Place[] =  await Promise.all(
              areas.map(async (area: Area) => {
                const [residential, commercial] = await Promise.all([
                  this.service.getResidentials(area.id),
                  this.service.getCommercial(area.id),
                ]);

                return new Place(area, residential, commercial);
              })
            );
            return new LoadPlacesSuccess(places);
          } catch (error) {
            return new LoadPlacesFail(error);
          }
        }),
        catchError((error) => of(new LoadPlacesFail(error)))
      )
    )
  );

We fetch all available areas and create a Place object for each one, containing information about the area along with residential and commercial data.

This results in an array of Place objects, each with nested data.

Our goal is to transition from using promises to using observables exclusively.

I am struggling to convert my current setup to use observable chains only. While I was able to retrieve both residential and commercial data simultaneously using combineLatest, I faced challenges when mapping over the areas array. It's crucial to handle nested subscriptions for each area without explicitly calling .subscribe().

How can I implement a nested combineLatest subscription for "each item"?

I experimented with a combination of from(), switchMap(), and combineLatest() but could not achieve the desired outcome. I kept getting arrays of observables instead of actual values.

Answer №1

This code snippet demonstrates a complex structure involving multiple forkJoin and map operators within a switchMap function.

switchMap((action: LoadPlaces) =>
  from(this.service.findAreas()).pipe(
    switchMap((areas: Area[]) => {
      return forkJoin( // Utilizing forkJoin 
        areas.map((area: Area) => { // Mapping to observables 
          return forkJoin([ // Another forkJoin operation
            from(this.service.getResidentials(area.id)), // Converting to observables
            from(this.service.getCommercial(area.id)),
          ]).pipe( // Mapping the result
            map(([residential, commercial]) => new Place(area, residential, commercial))
          );
        }) 
      ).pipe( // Mapping this result as well
        map(places => new LoadPlacesSuccess(places))
      );
    }),
    catchError((error) => of(new LoadPlacesFail(error)))
  )
)

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

Separate an array in TypeScript based on the sign of each number, and then replace the empty spaces with null objects

Hey, I'm facing a little issue, I have an Array of objects and my goal is to split them based on the sign of numbers. The objects should then be dynamically stored in different Arrays while retaining their index and getting padded with zeros at the b ...

What do you think about gulp-typescript and the latest @types typings for TypeScript?

I've added @types/jasmine as a development dependency. This is my gulp task for compiling TypeScript: gulp.task('compile:tests', ['compile:typescript', 'clean:tests'], function () { var project = ts.createProject(&a ...

API response containing JSON data is not being displayed properly in the webdatarocks angular component

I can't seem to figure out how to properly display the JSON formatted data returned by a REST API using Angular. Any suggestions on how to accomplish this? Here's what I've been attempting to do - fetchData() { this.service.fetchData().s ...

Adjusting the width of a div element horizontally in Angular 4 and

As someone new to Angular 4, I've been attempting to create a resizable div (horizontally) without success. My goal is to be able to click and drag a grabber to resize the text area horizontally. However, in the example provided in the link below, the ...

Substitute the specific class title with the present class

Here is a sample class (supposed to be immutable): class A { normalMethod1(): A{ const instance = this.staticMethod1(); return instance; } static staticMethod1: A(){ return new this(); } } The code above works fine, but how can I re ...

Eliminate redundant template code for Angular 2 components

Currently, I am developing a project using Angular 2 with the user-friendly Gentallela Alela HTML template. In many of my views, there are several components that share similar markup in their template files: <div class="col-md-12 col-sm-12 col-xs-12"& ...

Angular element fails to display properly

I'm currently working on developing a website using Angular and creating a header component. To generate the necessary files, I used the command ng g c commons/header which creates the HTML, SCSS, TS, and .spec.ts files. I then made modifications to t ...

Resolving the problem of Turkish uppercase dotted i when using the capitalization pipe in Angular 2

I have created a custom capitalization pipe that successfully capitalizes almost all characters, including converting the Turkish 'ı' character into 'I'. However, I am facing an issue where the 'i' character is also being con ...

Setting the root directory and output directory can be a bit tricky when dealing with source code scattered across multiple folders. Here's

Utilizing TypeScript in my Node.js project, I previously had a directory structure that looked like this: node_modules src -Models -Routes -Middlewares -Controllers -index.ts package.json tsconfig.json In ...

`mdTooltip in angular2-material does not have the capability to render HTML content

There seems to be an issue with using HTML in mdTooltip in angular2-material. Current package version for angular material: @angular/material": "2.0.0-beta.11 HTML Markup in Use: <span mdTooltip="<p>tooltip message</p>" mdTooltipPosit ...

Why is it that I am not receiving JSON data in my Angular application?

I am currently working on a class within a webapi public class ResponseObject { public int Success { get; set; } public string Message { get; set; } public object Data { get; set; } } Within my ASP.NetCore, I have the following method: publi ...

What is the best way to extract the ID from an event in TypeScript?

HTML Code: <ion-checkbox color="dark" checked="false" id="1on" (ionChange)="onTap($event)" ></ion-checkbox> TypeScript Code: onTap(e) { console.log(e); console.log(e.checked); } I am trying to retrieve the id of the checkbox. H ...

Enhancing external TypeScript modules

Currently, I am delving into the realm of enhancing external modules in TypeScript. I am diligently studying the official documentation and the DefinitelyTyped guides, poring over examples, and so forth. At this point, my goal is to incorporate custom prop ...

The element is implicitly assigned an 'any' type as the expression of type 'string' is unable to be used as an index within the type '{...}'

Trying to improve my react app with TypeScript, but encountering issues when typing certain variables. Here's the error message I'm facing: TypeScript error in /Users/SignUpFields.tsx(66,9): Element implicitly has an 'any' type becaus ...

generate a fresh array with matching keys

Here is an example array: subjectWithTopics = [ {subjectName:"maths", topicName : "topic1 of maths " }, {subjectName:"maths", topicName : "topic2 of maths " }, {subjectName:"English", topicName : &quo ...

Encountering the error "Cannot resolve all dependencies for CustomTranslationLoader" when executing Jest test cases in an Angular project

Attempting to create my initial test scenario for a login page, the contents of my ts file are as follows: import {Component, OnInit} from '@angular/core'; import {ActivatedRoute, Router} from '@angular/router'; import {FormBuilder, For ...

Binding textarea data in Angular is a powerful feature that allows

I am looking to display the content from a textarea on the page in real time, but I am struggling to get the line breaks to show up. Here is my current code snippet: app.component.html <div class="ui center aligned grid">{{Form.value.address}}< ...

Manipulate div display based on select value in Angular2 using [(ngModel)] with ion-select

I am currently working with ionic2 and angular2 using JavaScript, not TypeScript. I have two inputs: one for text and the other a select dropdown. My goal is to hide the text input if the value selected in the dropdown is 'more'. How can I achiev ...

Why is the Last Page display on pagination showing as 3 instead of 2 per items?

When working on Angular 13, I encountered an issue with applying pagination numbers like 1, 2, 3, etc. The problem I faced was that the last page Number should be 2, but it is displaying as 3. Why is this happening? To investigate the issue, I tested my ...

Generate a collection of items through replication

Develop a function that takes specific input and generates an array of objects with a length of 10 by incrementing the ID of each duplicate object. The first object in the output array should have "visible" set to true, while all others should have it set ...