Avoiding multiple HTTP requests on various subscribers in RXJS/Angular

I am currently utilizing the "mainData" service, which is composed of 3 key parts:

  • currentPage is utilized by the paginator component for page navigation and can be updated dynamically.
  • folders holds all folders within the current directory. This observable is used by 2 different components for listing folder content.
  • files contains all files within the current folder. This observable is utilized by 3 components for listing folder content.

The default view does not display any folders, so unnecessary HTTP calls should be avoided.

public currentPage = new ReplaySubject(1);
public folders: Observable<FLFolder[]>;
public files: Observable<FLFile[]>;

constructor(
  activatedRoute: ActivatedRoute,
  folderService: FolderService,
  fileService: FileService,
) {
  // Logic to populate `this.currentPage`
  
  // Internal observable only accessed by `folders` and `files`
  const folderIDAndPage: Observable<[string, number]> = combineLatest(
    activatedRoute.url.pipe(
      switchMap(segments => folderService.getFoldersFromSegments(segments)),
      distinctUntilChanged(),
    ),
    this.currentPage.pipe(
      distinctUntilChanged(),
    ),
  ).pipe(
    // Prevent multiple HTTP requests…
    publishReplay(1),
    refCount(),
  );

  this.folders = folderIDAndPage.pipe(
    switchMap(([folderID, page]) => folderService.getFfolders(folderID, page)),
    // Prevent multiple HTTP requests…
    publishReplay(1),
    refCount(),
  );

  this.files = folderIDAndPage.pipe(
    switchMap(([folderID, page]) => fileService.getFiles(folderID, page)),
    // Prevent multiple HTTP requests…
    publishReplay(1),
    refCount(),
  );
}

If neither folders nor files are subscribed to, no HTTP requests are made. However, if just one is subscribed to, both folders and files will be populated and updated simultaneously with a single HTTP call.

Answer №1

The functions <code>this.folders and this.files are not being utilized within this service at the moment. What could be happening with these components?

Is it possible that a refactor may be necessary? I apologize if my assumptions are incorrect.

I have structured my services using getters:

private _currentUser = new BehaviorSubject<User>({} as User);

You can then access it from a component by using the getter like so:

public getCurrentUser(): Observable<User> {
    return this._currentUser.asObservable();
}

This makes it clearer when calling the function.

Answer №2

Could you kindly implement the following modification in your code and give it a try -

const retrieveFoldersFromSegments$ = activatedRoute.url.pipe(
  switchMap(segments => folderService.getFoldersFromSegments(segments)),
  distinctUntilChanged(),
  publishReplay(1),
  refCount(),
);

/** This specific observable is internal, designated for use by `folders` and `files` */
const folderIDAndPage: Observable<[string, number]> = combineLatest(
  retrieveFoldersFromSegments$,
  this.currentPage.pipe(
    distinctUntilChanged(),
  ),
).pipe(
  // Finding a way to avoid redundant HTTP requests...
  publishReplay(1),
  refCount(),
);

On another note - You have employed take(1) with the activatedRoute.queryParams observable; This will restrict changes made to this.currentPage to occurring only once. However, you mentioned,

Can be updated at any point

So, doesn't that pose a contradiction? Or is it an intentional decision?

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

Error is being thrown due to defining a variable after it has already been declared and

Before I use a variable, I encountered the issue of using it before its definition, interface IProps extends WithStyles<typeof STYLES>; const STYLES = () => ({ }) Although it didn't cause any errors, a warning appeared: STYLES used befo ...

I'm curious about the correct method for updating a parent component using a shared service within the ngOnInit function in Angular version 13

There have been instances where I encountered a scenario multiple times, where I utilize a shared service within the ngOnInit of a component to update a value in another component, specifically its parent. This often leads to the well-known Error: NG0100: ...

Error: The function to create deep copies of objects is not working properly due to TypeError: Object(...) is not a

Encountering a TypeError: Object(...) is not a function in the following situation: To set up the state of a component with a specific Article (to be fetched from the backend in componentDidMount), I am implementing this approach // ArticlePage.tsx import ...

Best practices for organizing API Services using TypeScript and Next.js Server Actions

My product-actions/index file contains various server actions such as createProduct and getProductAssets, each of which verifies the user session before processing the request. I am looking for a way to check the session validity only once and then procee ...

"Series of Subscriptions: Unleashing New

I have a ReplaySubject that is subscribed to by multiple components. I am curious about the order in which these subscriptions are processed. public getValue$ = new ReplaySubject<any>(1); If I send a value to getValue$ using getValue$.next(5); Assu ...

In order for Angular jQuery click events to properly function, they must be triggered by a

My admin panel is built using jQuery and Bootstrap, and it functions properly when used outside of the Angular framework. However, after integrating jQuery and Bootstrap into an Angular project and configuring them, I noticed that I had to double click on ...

Crafting interactive buttons with angular material

I've been working on an angular application where I created 5 mat flat buttons using angular material. <button mat-flat-button [ngClass]="this.selected == 1 ? 'tab_selected' : 'tab_unselected'" (click)="change(1)">B-L1</b ...

Error encountered while injecting Angular dependencies in component constructor

Here is my newly created component. I am looking to allow users to adjust the count variable. import { Component, Inject } from '@angular/core'; @Component({ selector: 'app-likebtn', templateUrl: './likebtn.component.html&apos ...

Troubleshooting: Angular 13 input radio not recognizing checked condition

Storing selectedKitchenId in localstorage, and checking if selectedKitchenId === kitchen.id to determine which radio button should be selected. Cannot figure out why the checked condition is not working as expected, even though when I use a strong tag to d ...

Retrieve the individuals within the delimiter

Looking for a solution to modify the characters within square brackets in a given string. For instance, I have a string that looks like "[A] [B] this is my [C] string". How can I update these bracketed characters by adding or removing brackets? ...

The dependency that was installed in the node_modules directory is now showing as missing the

I have encountered an issue with 2 TS packages. The first package, project-1, is installed as a dependency in the second package, project-2. While I am able to import and access all type definitions of project-1 in project-2, the dependencies (node_modules ...

Angular Material - Data Table Kit

Struggling with setting custom styling for a mat-table in Angular Material. I want to adjust the border radius of the table and change the spacing inside to "space-between". The design I'm aiming for is shown here: Design Any tips or suggestions woul ...

Reactive sidenav in action with Angular

Exploring the creation of a reactive component for educational purposes, disregarding project structure =). My directory layout: app.component.html <app-header></app-header> <app-sidenav></app-sidenav> <app-footer></app ...

Tips for typing a narrow JSX.Element

Is there a way to create a variable in React that can be either a component or a string? Like this: function MyComponent(): JSX.Element { let icon: JSX.Element | string = "/example.png"; return <div>{typeof icon === "JSX.Element" ? icon : <i ...

The datepicker is functioning correctly, however, the displayed value does not reflect the updated date

The version of angularjs being used is 1.5.11. Within my .NET MVC project, the bs-datepicker element from angularjs is incorporated. Featured below is the datepicker component accompanied by a pair of images functioning as buttons within my application: & ...

Setting up a Docker configuration for an Angular project

Apologies for my imperfect English. I am new to Docker and finding it challenging. Currently, I am trying to configure this project: After adding two files https://i.sstatic.net/NyEcN.png This is my docker-compose file web: build: . ports: ...

ESLint's no-unused-vars rule is triggered when Typescript object destructuring is employed

I'm encountering an issue with my Typescript code where I am destructuring an object to extract a partial object, but it's failing the linter check. Here is the problematic code snippet: async someFunction(username: string): Promise<UserDTO> ...

Having trouble implementing ng2-charts in Angular 4 when using shared components

Using angular 4.0.0, angular-cli 1.2.1, and ng2-charts 1.6.0 has been a smooth experience for me so far. However, I encountered an issue when trying to incorporate ng2-charts into "shared" components. In my setup, I have a shared-components.module that is ...

Converting javascript html object lowercase

Is there a way to dynamically adjust the height of specific letters in my label? Right now, I am overriding the text for the elements: let element = document.getElementById('xxx') element.textContent = 'Label' I attempted using <sup ...

Define the output type of an arrow function within an interface signature

How can I inform typescript that I will be utilizing an interface containing a function called "foo" which always returns a string. The implementation of the function will be specified by the object implementing the interface. For example: export interfac ...