ShareReplay

You generally want to use shareReplay when you have side-effects or taxing computations that you do not wish to be executed amongst multiple subscribers. It may also be valuable in situations where you know you will have late subscribers to a stream that needs access to previously emitted values. This ability to replay values on subscription is what differentiates share and shareReplay.

In other words. If we have two different subscriptions to the same HTTP service method, for example, we can only make one call and share the information received from the results to both subscriptions by using the share replay operator. We only need to make one call to and share the information with all the subscriptions needed.

For instance, suppose you have an observable that emits the last visited URL. In the first example we are going to use share:

// simulate url change with subject
const routeEnd = new Subject<{data: any, url: string}>();

// grab url and share with subscribers
const lastUrl = routeEnd.pipe(
  pluck('url'),
  share()
);

// initial subscriber required
const initialSubscriber = lastUrl.subscribe(console.log);

// simulate route change
routeEnd.next({data: {}, url: 'my-path'});

// nothing logged
const lateSubscriber = lastUrl.subscribe(console.log);

In the above example nothing is logged as the lateSubscriber subscribes to the source. Now suppose instead we wanted to give access to the last emitted value on subscription, we can accomplish this with shareReplay:

import { Subject } from 'rxjs/Subject';
import { ReplaySubject } from 'rxjs/ReplaySubject';
import { pluck, share, shareReplay, tap } from 'rxjs/operators';

// simulate url change with subject
const routeEnd = new Subject<{data: any, url: string}>();

// grab url and share with subscribers
const lastUrl = routeEnd.pipe(
  tap(_ => console.log('executed')),
  pluck('url'),
  // defaults to all values so we set it to just keep and replay last one
  shareReplay(1)
);

// requires initial subscription
const initialSubscriber = lastUrl.subscribe(console.log);

// simulate route change
// logged: 'executed', 'my-path'
routeEnd.next({data: {}, url: 'my-path'});

// logged: 'my-path'
const lateSubscriber = lastUrl.subscribe(console.log);

Information and references are taken from https://www.learnrxjs.io/learn-rxjs/operators/multicasting/sharereplay

Real snippet code about how to use shareReplay operator:

// Run our observable
const http$ = CreateHttpObservable('/api/courses');

// Let's map our results
const courses$: Observable<any[]> = http$.pipe(
  tap(() => console.log('HTTP executed')),
  map(res => Object.values(res.payload)),
  shareReplay()
);

// Let map only the beginner courses
this.beginnerCourses$ = courses$.pipe(
  map(
    courses => courses
      .filter((course: { category: string; }) => course.category === 'BEGINNER'))
);

// Let map only the advance courses
this.advanceCourses$ = courses$.pipe(
  map(
    courses => courses
      .filter((course: { category: string; }) => course.category === 'ADVANCED'))
);

Maybe you are wondering why there is no subscriptionmethod, well that's because we are using the async pipe to run the subscription.

As you can see there is only one call to the backend:

Last updated