Combine all the missing observables in RxJS into a single array

In my code, I am creating a NavBar with items that may require fetching extra information from an API and adding it to the subtitle field.

I want to transform this into an Observable<NavItem[]> so that it can be rendered using an Async Pipe.

Currently, the code logs each NavItem before calling ops.toArray(). However, the log call after ops.toArray() never completes...

Is there a more efficient RXJS approach to combine these items into an Observable<NavItem[]> ?

import * as ops from 'rxjs/operators';

navItem$: Observable<NavItem[]> = null

this.navItem$ = this.store.pipe(
  select(fromRoute.selectLastUrls),
  ops.map((d) => {
    // Initial creation of NavItems
  }),
  ops.tap((i) => console.log(i)), // Prints an array of 5 NavItems as expected
  ops.mergeAll(),
  ops.mergeMap((i) =>
    iif(
      () => i.listItem,
      // Make API calls for certain list items (To include subtitle details)
      this.backendService.find({ title: [i.title] }).pipe(
        ops.map((found) => ({...i, subtitle: found.items[0].info,})),
      ),
      of(i),
    ),
  ),
  ops.tap((i) => console.log(i)), // Each log line should contain 1 NavItem with data retrieved from API calls
  ops.toArray(),
  ops.tap((i) => console.log(i)) // This line fails to log
);

Answer №1

in this particular scenario, the function toArray is programmed to wait for the entire stream to finish before compiling all elements into a single array.

If you want this operation to only apply to grouped items, you will need to nest the operators one level deeper. Below is an example of how to achieve this:

this.navItem$ = this.store.pipe(
  select(fromRoute.selectLastUrls),
  ops.map((d) => {
    // Initial setup of NavItems
  }),
  ops.tap((i) => console.log(i)), // Outputs an array of 5 NavItems as anticipated
  ops.switchMap(arr => from(arr).pipe(
     ops.mergeMap((i) =>
       iif(
        () => i.listItem,
         // Fetch additional details from API for list items (e.g., subtitle)
         this.backendService.find({ title: [i.title] }).pipe(
           ops.map((found) => ({...i, subtitle: found.items[0].info,})),),
         of(i),
       ),
     ),
     ops.tap((i) => console.log(i)), // Each log line should display 1 NavItem with data retrieved from API calls
     ops.toArray(),
    ))
  
  ops.tap((i) => console.log(i)) // Logs arrays after the modification
);

It's worth noting that importing all operators using

import * as ops from 'rxjs/operators';
is not recommended because it may result in unnecessary operators being included in the bundle. Importing each operator individually allows for better tree-shaking and a smaller final bundle size.

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

Is there a way to automatically populate the result input field with the dynamic calculation results from a dynamic calculator in Angular6?

My current challenge involves creating dynamic calculators with customizable fields. For example, I can generate a "Percentage Calculator" with specific input fields or a "Compound Interest" Calculator with different input requirements and formulas. Succes ...

MUI provides the flexibility to adjust the opacity separately for Chip labels/icons and backgrounds

My objective is to customize the opacity of label/icon and background in MUI Chip. I want the label & icon to have an opacity of 1, while the background should have an opacity of 0.0571. Technologies used in this project include React, TypeScript, Materia ...

Utilizing event listeners with image elements in React for interactive typing experience

When I attempt to type the event as React.ChangeEvent<HTMLImageElement> in order to make the e.target.src work, I encounter the following error messages in the imageFound and ImageNotFound functions: Type '(evt: React.ChangeEvent) => void&a ...

Optimizing Node.js and Express routes by separating them into individual files: a

When using Express in a Node project along with Typescript, what are the best practices for express.Router? For instance, it is recommended to follow a directory structure like this: |directory_name ---server.js |--node_modules |--routes ---in ...

What are the advantages of combining the website URL and API URL within the Angular service?

When deploying my application in a production environment, I encounter an issue with the URL addresses. The web address is , while the API address is . However, when making a request to the API through Angular, the URLs get concatenated into . This issue d ...

Guide on importing TypeScript types into Vuetify 3

Exploring the use of the ValidationRule type from the Vuetify library (check out the docs and source code), I'm facing difficulties importing it into my Vue.js component. I have attempted to import the type in different ways, such as: import type { V ...

Angular 12 is throwing an error due to the undefined @Input property

The issue presents a simple problem to comprehend yet proves challenging to resolve. There are 2 key components involved: CustomerComponent (Parent) InvoiceComponent (Child) Currently, I'm passing customer details using <admin-invoice-form [custo ...

Capacitor-enabled Ionic Audio Recording

Finally completed my chat app, but I am looking to enhance the voice messaging feature to be more in line with Messenger rather than a standard file.wav format. Any suggestions or ideas would be greatly appreciated! https://i.stack.imgur.com/soXZC.png Cu ...

Strategies for Handling Errors within Observable Subscriptions in Angular

While working with code from themes written in the latest Angular versions and doing research online, I've noticed that many developers neglect error handling when it comes to subscription. My question is: When is it necessary to handle errors in an ...

What is the method to activate a click event on an input file when a button is clicked in Angular 2?

<input type="file" accept="image/*"> <button>Upload file</button> Is there a way to activate the input type=file click event using the button's click event in Angular 2? ...

Fixing prop passing issues in Vue.js components to prevent errors

My Vue-cli install with TypeScript is set up to render JSX using a boilerplate. However, I am facing an issue when trying to pass a property to the HelloWorld component. Here's what my code looks like: export default Vue.extend({ name: 'App&apo ...

Utilizing type maps within nested objects in Typescript: A comprehensive guide

Initially, a type is established that connects enum keys with specific types: enum MyEnum { A, B } type TypeMap = { [MyEnum.A]:string, [MyEnum.B]:number } interface ObjInterface<T extends keyof TypeMap> { obj: T, objData: Ty ...

Creating a type definition for the createSelector function based on the useQuery result

Struggling to find the correct typings for the createSelector res parameter from redux-js, especially in TypeScript where there are no examples or explanations available. The only guidance is provided in JS. const selectFacts = React.useMemo(() => { ...

Is there a surefire method to ensure that ChromeDriver in Protractor consistently uses the stable version?

Every time Chrome releases an update, I encounter a recurring issue. Allow me to paint the picture: All browsers are at version 83 of Chrome Chrome announces that version 84 is on its way, but it has not been released yet. A new ChromeDriver 84 is rolled ...

"Looking for a way to create a new line in my particular situation. Any tips

Here is the code snippet I am working with: let list: Array<string> =[]; page.on('request', request => list.push('>>', request.method(), request.url()+'\\n')); page.on('respon ...

Develop an Angular application with a customized URL path that utilizes a ServiceWorker

I am currently working on an Angular 10 application. It utilizes the Angular "service worker" to transform into a PWA. Once the app is compiled, it resides in "c:\-website-folder-\ng-app\dist". Users can access the app through a URL like: ...

Using single-spa with Angular Parcel inside a mat-dialog

I have developed an Angular application and an Angular parcel that will be utilized by various applications within the organization utilizing different frameworks. When I try to display the parcel component directly in another component using the async c ...

The Angular NgFor directive can only be used to bind data to Iterables like Arrays

I am encountering an issue when attempting to iterate through and display data using ngFor. The specific error appearing in the console is "Error: Cannot find a differ supporting object '[object Object]' of type 'object'. NgFor only su ...

One should refrain from loading the API in Angular when there is no data present, by utilizing the global.getData method

Check out this code snippet: loadNextBatch() { console.log('scrolldown'); this.pageIndex = this.pageIndex + 1; this.global.getData(`/conditions/latest?start=${this.pageIndex}&length=${this.pageSize}`) .pipe(take(1)).subscr ...

Creating interactive forms with Angular 9 using ngx-formly and arrays for dynamic form generation

Looking to implement: Dynamic Forms based on user-selected locale JSON using ngx-formly/material. How can I connect fields with my array of objects "this.fields2"? In my component.ts file, I have: model: any = {}; options: FormlyFormOptions = {}; fields: ...