What are the steps to creating a service that can fetch values asynchronously and carry out tasks such as filtering on the received data?

Our root-based service offers the following features:

  • Retrieves data once from an API
  • Handles data mapping
  • Shares data with other components when necessary

This data remains static throughout the app's lifecycle and only refreshes when the user reloads the browser. Since all data will be utilized, making HTTP requests for each getOneById() call is inefficient. A filter performs faster in this scenario.

The structure of the service resembles this:

export class MyTypeService {
  items: MyType[] = [];
  items$ = new BehaviorSubject<MyType[]>(this.items);

  constructor(private http: HttpClient) { }

  getData(): Subscription {
    return this.http.get<SearchResult>(
      'path'
    ).pipe(
      map((response: any) => {
        this.items = response;
        return this.items;
      }),
      catchError(error => {
        // omitted for simplicity
        this.handleError(error);
        return of([]);
      })
    ).subscribe(result => this.items$.next(result));
  }

  getOneById(id: string): MyType|null {
    for (let item of this.items) {
      if (item.id === id) {
        return item;
      }
    }

    return null;
  }
}

Now facing these questions:

  • Should the service itself subscribe to items$?
    Or should all member functions like getOneById() subscribe?
    (Which might mean that items can be removed)
  • Is it best to invoke getData() in the constructor since values are crucial during runtime?
    Or wait until the values are actually required?
  • How do I notify a component that it's safe to use getOneById()?

Answer №1

Avoid having items without Observable in your code. To prevent unnecessary HTTP requests, consider implementing the following solution:

  itemsSub: BehaviorSubject<any[]> = new BehaviorSubject(null);

  getItems(): Observable<any[]> {
    return this.itemsSub.pipe(mergeMap(items => {
      if (items) {
        return of(items); // Return items if they already exist
      } else {
        // If items don't exist, fetch them and update the subject
        return this.http.get().pipe(tap((items) => this.itemsSub.next(items))); 
      }
    }))
  }

  getItemsFiltered() {
    return this.getItems().pipe(filter(items => !!items));
  }

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

What could be causing the issue with two-way binding in mat-table?

I'm currently working on implementing a table using Angular Material. My goal is to have an input field available in each row, allowing the user to enter data that will be saved along with the rest of the table. Below is a snippet of the code I am u ...

Tips for retrieving a single record from Firebase using Angular 2

I am struggling to retrieve a single record by uid from my Firebase database in an Angular 2 app. The issue I am facing is that the profile variable always returns as undefined. Can someone guide me on the correct approach to solving this? Thank you! My co ...

Angular route unable to detect Passport User Session

The navigation bar in the header features buttons for Register, Login, and Become a Seller. Upon user login, it displays logout and view profile buttons. This functionality is operational on all routes except one, causing a client-side error. user not def ...

Is there anyone who can help clarify the best practices for integrating Twitter Bootstrap and Angular 4 seamlessly?

Recently, I've been experimenting with Angular (4.x.x) and wanted to incorporate the sleek design of Twitter Bootstrap into my project. However, I quickly discovered that using Bootstrap requires jQuery, which contradicts the common advice of avoidin ...

Is there a way to prevent future dates from being selected on angular p-calendar?

I need help with disabling future dates in a calendar datepicker input field. Here's how I'm currently using it: <p-calendar maxDate="dateTime" showTime="true" hourFormat="12" showButtonBar="true" [(ngModel)]="dateTime" name="timeOfUse" requ ...

Implementing a Single handleChange Event for Multiple TextFields

How can I use the same handleChange event for multiple TextFields in React? import * as React from "react"; import { TextField} from 'office-ui-fabric-react/lib/TextField'; export interface StackOverflowState { value: string; } export de ...

Is there a way to implement ngModel within a loop?

I am facing a challenge in my Angular application where I need to change the value of ngModel based on the items in the license. However, while looping through my .ts file, I noticed that ngModel is taking the last value of test even for items not present ...

Guide on utilizing a module to define numerous elements in Angular 6

I am trying to use the joke.module.ts module to specify multiple components. Starting with JokeComponent in joke/joke.module.ts within the src/app directory. import { Component } from '@angular/core';/ @Component({ selector: 'joke', ...

Ways to eliminate the need for margin adjustments when buttons are shown in Responsive mode

I am currently utilizing Angular 14 along with SCSS Within a dialog component, I have two buttons displayed horizontally. The first button displays the text I am feeling lucky, while the second button displays Not lucky. There should be a separation of 20 ...

What are the steps to turn off the color display of the "ng build" command?

Is there a method to deactivate the colorized output of the Angular CLI ng build command? Specifically, I am looking to disable the colorful summary that is displayed on the console upon completion. I'm hoping for a solution such as an environment var ...

Transferring information to a complex and deeply embedded Angular component

In my current component structure, A includes B, B includes C, and C includes D. I am looking to transfer data from the topmost component (A) to the one at the bottom of the hierarchy (D). Should I utilize data binding in HTML templates, which would requ ...

Can you explain the purpose of the argument provided to @Resolver in type-graphql?

I'm genuinely curious about something. I noticed on the type-graphql documentation website that they include an argument in the @Resolver decorator. You can see this in action on their page here: (look under the "Resolvers" section). Here is a snipp ...

agm-circle has such a high drag sensitivity in angular 4

I have implemented an agm-circle in an agm-map within Angular 4. Everything is working as expected, however, I am experiencing an issue with the speed at which the circle moves when dragged. Is there a way to slow down this movement? Below is my code sni ...

Vue warning: Issue in rendering: "TypeError: Circular structure being converted to JSON"

After successfully creating a Single File Component in Vue without any compilation errors, I faced an issue when trying to view the component through its route link. Instead of the expected page, I encountered a stack trace printed in the Chrome browser us ...

Using async method in controller with NestJS Interceptor

I am seeking a way to capture both the result and any potential errors from an asynchronous method within a controller using an interceptor. When an error is thrown, the interceptor can respond accordingly. However, I am struggling to figure out how to tri ...

Despite my efforts to properly run, my angular component is still not being added to the angular module

After attempting to execute ng generate component elements/ElementsHome, I encountered a successful run; however, the terminal did not display the Updated file path as a hyperlink. Instead, it indicated that the component was not created within the module. ...

Struggling to compile your Angular 2 application in Visual Studio 2015?

After carefully following all the steps outlined in the VISUAL STUDIO 2015 QUICKSTART documentation, I have also gone ahead and installed the "Microsoft .NET Core 1.0.1 VS 2015 Tooling Preview 2", even though it was not specifically mentioned in the docume ...

Issue with Angular failing to include Bearer token in API requests

Given that this explanation has become lengthier than anticipated, here's a tl;dr: My situation involves an Angular application not transmitting the bearer token received from Azure AD to the API, resulting in a 401 response being returned. The setup ...

How might the issue of update activation affecting lazy loading in an Angular PWA app specifically manifest itself?

I am looking for a way to trigger an update activation in my Angular PWA app. I came across a note in the documentation from the official Angular website (https://angular.io/guide/service-worker-communications) that says: "Doing this could break lazy-load ...

Adjust the color of the entire modal

I'm working with a react native modal and encountering an issue where the backgroundColor I apply is only showing at the top of the modal. How can I ensure that the color fills the entire modal view? Any suggestions on how to fix this problem and mak ...