fulls1z3 / ngx-cache

Cache utility for Angular
MIT License
154 stars 16 forks source link

Store in cache observable itself but not it's value #115

Open LendaVadym opened 5 years ago

LendaVadym commented 5 years ago

I'm submitting a ... (check one with "x")

[ ] Regression (a behavior that used to work and stopped working in a new release)
[ ] Bug report  <!-- Please check the repository for a similar issue or PR before submitting -->
[x] Support request => <!-- Please check the repository for a similar issue or PR before submitting -->
[x] Feature request
[ ] Documentation issue or request

Current behavior Currently, if decorated with @Cached method returns observable we are waiting for observable to emit data (pipeble method map is used) to save this data in cache. It's not working with cold observables when f.e. several angular services request the same data (http) simultaneously at startup. Each service will receive its own observable and several remote calls will be invoked. The last returned value will be stored in cache.

Expected/desired behavior Wouldn't it be more correct to store in cache the returned from decorated method observable itself (f.e. as ReplaySubject)? Then every subsequent call to the decorated method will return the same observable and every angular service that invoke decorated method can subscribe tho this observable and get data.

Minimal reproduction of the problem with instructions

What is the motivation / use case for changing the behavior? To reduce number of remote calls if decorated with @Cached method is called simultaneously several times.

Environment

LendaVadym commented 5 years ago

Code from @Cached decorator:

How it's currently implemented: ...

const value = method.apply(this, args);
if (isObservable(value)) {
   return value.pipe(
      map((res: any) => {
         cache.set(cacheKey, res, ReturnType.Observable);
            return res;
          })
        );
      }

...

Proposition: ...

if (isObservable(value)) {
   const subject = new ReplaySubject<any>(1);
   value.subscribe(
         (next) => { 
            subject .next(r); 
         },
         (error) => {
            // possibly clear subject from cache;
            subject .error(e);
         },
         () => subject .complete()
      );

   cache.set(cacheKey, subject.asObservable(), ReturnType.Observable);   
}
fulls1z3 commented 4 years ago

@LendaVadym sorry for the delay, had busy times. feel free to fire a PR and i'll approve.