user3345721
user3345721

Reputation: 85

Why does the rxjs share operator not work as expected when the observable is in service

I try to use rxjs share operator in two different ways.

  1. Using it in the component

Component:

constructor() {
    const obs1 = interval(1000).pipe(
      tap(x => console.log('processing in comp1')),
      map(x => x * x),
      take(1),
      share()
    );

    obs1.subscribe(x=>console.log('testShare1'))
    obs1.subscribe(x=>console.log('testShare2'))
  }

Result:

processing in comp1  
testShare1
testShare2

It works as expected.

  1. Calling it from an external service.

Service:

export class TestShareService {
  constructor() { }
  testShare() {
    const obs1 = interval(1000).pipe(
      tap(x => console.log('processing in service ')),
      map(x => x * x),
      take(1),
      share()
    );

    return obs1;
  }
}

Component:

constructor(private shareSrv: TestShareService) {
    shareSrv.testShare().subscribe(x=>console.log('testShare1 using service'));
    shareSrv.testShare().subscribe(x=>console.log('testShare2 using service'));

   }

result:

processing in service  
testShare1 using service
processing in service  
testShare2 using service

It looks like rxjs share operator does not affect when the observable is in an external service. Is is right? Or what am I doing wrong?

Thank you.

Upvotes: 1

Views: 379

Answers (1)

Adrian Brand
Adrian Brand

Reputation: 21638

You need to assign the observable to a property on the service rather than create a new one with a function call.

export class TestShareService {
  private params$ = new BehaviorSubject<ParamsType | null>(null);
  
  data$ = params$.pipe(
    filter(params => params !== null), // filter out the initial null
    switchMap(params => this.http.get<YourResponseType>(params)),
    share()
  );

  get(params: ParamsType) {
    this.params$.next(params);
  }

  constructor(private http: HttpClient) {}
}

Now any subscriber to the observable data$ will be sharing the same instance of the same observable rather than a new observable each time the function is called. Any time the get function is called it will trigger the chain to make another http call.

Upvotes: 1

Related Questions