Caching observables causing problem with mergeMap

201 Views Asked by At

I have a caching method in a container:

get(): Observable<T[]> {
  if (!this.get$) {
    this.get$ = merge(
      this.behaviorSubject.asObservable(),
      this._config.get().pipe(shareReplay(1), tap(x => this.behaviorSubject.next(x))));
  }

  return this.get$;
}

This works fine with normal observables, however when I cache the bellow in a myContainer2 (e.g using cached observable's result to create another cached observable) method like:

// get is assigned to _config.get in the above function
const myContainer2 = new Container({get: () => myContainer1.get().pipe(mergeMap(res1 => getObs2(res1))});

// please note, the end goal is to resolve the first observable on the first subscription 
// and not when caching it in the above method (using cold observables)
myContainer2.get().subscribe(...) // getObs2 gets called
myContainer2.get().subscribe(...) // getObs2 gets called again
myContainer2.get().subscribe(...) // getObs2 gets called for a third time, and so on

every time when the second cache is subscribed to getObs2 gets called (it caches nothing). I suspect my implementation of get is faulty, since I am merging an behavior subject (which emits at the beginning), but I cant think of any other way to implement it (in order to use cold observables). Please note that if I use normal observable instead of myContainer.get() everything works as expected. Do you know where the problem lies?

1

There are 1 best solutions below

1
On

Using a declarative approach, you can handle caching as follows:

// Declare the Observable that retrieves the set of 
// configuration data and shares it.
config$ = this._config.get().pipe(shareReplay(1));

When subscribed to config$, the above code will automatically go get the configuration if it's not already been retrieved or return the retrieved configuration.

I'm not clear on what the BehaviorSubject code is for in your example. If it was to hold the emitted config data, it's not necessary as the config$ will provide it.