I am looking for an Angular Observable that only returns a single value without any initial value

Is there a way to create an Observable-like object that calls a webservice only once and shares the result with all subscribers, whether they subscribe before or after the call?

Using a Subject would provide the result to subscribers who subscribed before the call, not after.

const s: Subject<number> = new Subject();
s.next(1);
s.subscribe(x => {console.log(x)}); // will not print anything

A BehaviourSubject requires an initial dummy value, which means subscribers who signed up before the call will receive this placeholder value instead of the actual result.

const s: BehaviorSubject<number> = new BehaviorSubject(123);
s.subscribe(x => {console.log(x)}); // will print dummy value 123, then 1
s.next(1);

I attempted to create my own custom Observable, but encountered the issue of potentially calling the webservice multiple times.

let val: number|undefined = undefined;
const s = new Observable((observer) => {
  if (val !== undefined) {
    observer.next(val);
  } else {
    doMyHttpCall().subscribe({
      response => {
        this.val = 1;
        observer.next(val);
    });
  }
});
s.subscribe(x => {console.log(x)});
s.subscribe(x => {console.log(x)});   // two clients may give two calls

What is the correct approach to achieve this functionality?

Answer №1

If you want to efficiently share an observable response from your webservice without making duplicate calls, the solution lies in utilizing the shareReplay operator.

export class WebService {

  data$ = this.http.get(ENDPOINT).pipe(
    shareReplay(1)
  );

  constructor(private http: HttpClient) { }

}

When a consumer subscribes to data$ for the first time, the http.get() call will be triggered. Subsequent subscribers will then receive the cached response instead of triggering additional requests.

For a live demonstration, check out this StackBlitz demo

Answer №2

In my opinion, I would approach this by using a BehaviorSubject that initially starts as null, as demonstrated below:

const subject = new BehaviorSubject<number | null>(null);
subject.subscribe(value => {
  if (!value) 
    return;

  console.log(value)
});
subject.next(1);

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 message: Unable to locate Bootstrap call in standalone Angular project after executing 'ng add @angular/pwa' command

Having an issue while trying to integrate @angular/pwa, it keeps showing me an error saying "Bootstrap call not found". It's worth mentioning that I have removed app.module.ts and am using standalone components in various places without any module. Cu ...

error: encountering issue with Vue TypeScript Jest tests - '$store' property is undefined

I've been facing issues with my tests failing after a recent npm install. I've tried adjusting versions up and down, but haven't had any success. Interestingly, the $store isn't directly used in any of the components or tests. Despit ...

Display the HTML tag inside a cell of a mat-table

I am currently exploring options to display an HTML tag within a cell of a mat-table in Angular. My goal is to show a colored circle next to the cell value. I have searched online for solutions, but haven't found one that works. If anyone has any insi ...

Creating a dynamic list from an array of strings in Angular: A step-by-step guide

Within my .ts component file, I have declared a variable called campaignList as an array of strings. campaignList: string[] I am dynamically populating this list programmatically. In the corresponding HTML file, I have set up a table structure with heade ...

Angular data table is currently displaying an empty dataset with no information available

While attempting to display a data table in Angular JS, an issue arose where the table showed no available data despite there being 4 records present. Refer to the screenshot below for visual reference. https://i.sstatic.net/hdaW9.png This is the approac ...

Encountering a Typescript issue stating "Property 'then' does not exist" while attempting to chain promises using promise-middleware and thunk

Currently, I am utilizing redux-promise-middleware alongside redux-thunk to effectively chain my promises: import { Dispatch } from 'redux'; class Actions { private static _dispatcher: Dispatch<any>; public static get dispatcher() ...

typescript ways to exclude enum values

I am working with enums in TypeScript. enum Status { Cancelled = 'cancelled', Completed = 'completed', Created = 'created' } Now, I need to create another enum that includes only the values Completed and Created. enum S ...

Is there a way to efficiently execute an API function for every element within an array in a sequential manner?

I am currently facing a challenging problem while working with Angular and RxJs. I have an array containing several IDs: ids = [1,2,3,4] There is an API that can be called with a specific ID parameter to delete the corresponding item from the database: th ...

Using the VSCode debugger to place a breakpoint within a Typescript package that has been symlinked using `npm link`

I'm currently troubleshooting a NodeJS application and its associated typescript packages, which have been linked using `npm link`. The directory structure is as follows: /root/package-a # typescript package /root/package-b # another typescript packa ...

Asynchronous function in TypeScript is restricting the return type to only one promise type

Using node version 14.7.0, npm version 6.14.7, and typescript version 3.7.3. I have a function that interacts with a postgres database and retrieves either the first row it finds or all results based on a parameter. It looks something like this: async fet ...

Angular 7 SPA encountering Media Type Not Supported 415 issue when communicating with .NET, despite successful request in Postman

My SPA is encountering a 415 Unsupported Media Type Error when it calls a specific endpoint in my .NET API that I recently implemented pagination for. Interestingly, the same call from Postman is successful without any errors. It's puzzling why the id ...

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 ...

Is it possible to programmatically include a getter method to a class in JavaScript or TypeScript?

My current focus is on TypeScript and I'm exploring the decorators functionality. I would greatly appreciate some guidance or expert knowledge on JavaScript capabilities in this area. I am curious about dynamically adding a getter method to a Prototy ...

Guide on utilizing the useContext hook in React/Next.js while incorporating TypeScript

As I embark on my journey in the world of TypeScript, I find myself working on a new project in Next.js using TypeScript. My goal is to incorporate authentication functionality into this project by utilizing createContext. Coming from a background in JavaS ...

The system encountered an issue: unable to determine the property 'endsWith' of an undefined value

As I delve into writing my initial unit tests for the components, certain issues have arisen: TypeError: Cannot read property 'endsWith' of undefined. How can I define the data.iconPath in my test to resolve this error? Presenting my component ...

Update the input field's placeholder with the current date

Is it possible to dynamically set the placeholders for <input type='date' placeholder='{{ 'currentDate' }}'>? I have tried using the following variable: currentDate = this.datePipe.transform(new Date(), "yyyy-MM-dd& ...

Delivering static HTML routes in a React App using Typescript

I am working on a React app with functional components, and everything is working perfectly with its own CSS. Now, I have a separate static HTML file (FAQ) with its own CSS and design that I want to incorporate as a new route at /FAQ. I don't want th ...

Angular 5 Service Unit Testing for UPDATE Function

Currently, I am implementing a stepper feature with back, step, next steps. On the last step, when the user clicks 'done,' I need to call a service to update user data. While I have successfully tested the backStep() and nextStep() methods, I now ...

Are multiple click events needed for identical buttons?

In my component, there is an HTML structure like this: <div id="catalogo" class="container"> <div class="row"> <div *ngFor="let artista of artistas" class="col-sm" style="mar ...

What is the best way to utilize the `Headers` iterator within a web browser?

Currently, I am attempting to utilize the Headers iterator as per the guidelines outlined in the Iterator documentation. let done = false while ( ! done ) { let result = headers.entries() if ( result.value ) { console.log(`yaay`) } ...