ngx-cacheable
Advanced tools
Comparing version 1.0.7 to 1.0.8
import { combineLatest, forkJoin, Observable, Subject, timer } from 'rxjs'; | ||
import { mapTo, startWith } from 'rxjs/operators'; | ||
import { CacheBuster } from './cache-buster.decorator'; | ||
import { Cacheable } from './cacheable.decorator'; | ||
import { Cacheable, globalCacheBusterNotifier } from './cacheable.decorator'; | ||
@@ -694,2 +694,91 @@ const cacheBusterNotifier = new Subject(); | ||
}); | ||
it('should clear all caches when the global cache buster is called', () => { | ||
/** | ||
* set up a service with multiple cached methods | ||
*/ | ||
class Service { | ||
mockServiceCall(parameter) { | ||
return timer(1000).pipe(mapTo({ payload: parameter })); | ||
} | ||
@Cacheable() | ||
getData1(parameter: string) { | ||
return this.mockServiceCall(parameter); | ||
} | ||
@Cacheable() | ||
getData2(parameter: string) { | ||
return this.mockServiceCall(parameter); | ||
} | ||
@Cacheable() | ||
getData3(parameter: string) { | ||
return this.mockServiceCall(parameter); | ||
} | ||
} | ||
const service = new Service(); | ||
mockServiceCallSpy = spyOn(service, 'mockServiceCall').and.callThrough(); | ||
/** | ||
* call the first method and cache it | ||
*/ | ||
service.getData1('test1'); | ||
const asyncFreshData1 = _timedStreamAsyncAwait( | ||
service.getData1('test1'), | ||
1000 | ||
); | ||
expect(asyncFreshData1).toEqual({ payload: 'test1' }); | ||
const cachedResponse1 = _timedStreamAsyncAwait(service.getData1('test1')); | ||
expect(cachedResponse1).toEqual({ payload: 'test1' }); | ||
/** | ||
* even though we called getData1 twice, this should only be called once | ||
* since the second call went straight to the cache | ||
*/ | ||
expect(mockServiceCallSpy).toHaveBeenCalledTimes(1); | ||
service.getData2('test2'); | ||
const asyncFreshData2 = _timedStreamAsyncAwait( | ||
service.getData2('test2'), | ||
1000 | ||
); | ||
expect(asyncFreshData2).toEqual({ payload: 'test2' }); | ||
const cachedResponse2 = _timedStreamAsyncAwait(service.getData2('test2')); | ||
expect(cachedResponse2).toEqual({ payload: 'test2' }); | ||
expect(mockServiceCallSpy).toHaveBeenCalledTimes(2); | ||
service.getData3('test3'); | ||
const asyncFreshData3 = _timedStreamAsyncAwait( | ||
service.getData3('test3'), | ||
1000 | ||
); | ||
expect(asyncFreshData3).toEqual({ payload: 'test3' }); | ||
const cachedResponse3 = _timedStreamAsyncAwait(service.getData3('test3')); | ||
expect(cachedResponse3).toEqual({ payload: 'test3' }); | ||
expect(mockServiceCallSpy).toHaveBeenCalledTimes(3); | ||
/** | ||
* bust all caches | ||
*/ | ||
globalCacheBusterNotifier.next(); | ||
_timedStreamAsyncAwait( | ||
service.getData1('test1'), | ||
1000 | ||
); | ||
_timedStreamAsyncAwait( | ||
service.getData2('test2'), | ||
1000 | ||
); | ||
_timedStreamAsyncAwait( | ||
service.getData3('test3'), | ||
1000 | ||
); | ||
/** | ||
* if we didn't bust the cache, this would've been 3 | ||
*/ | ||
expect(mockServiceCallSpy).toHaveBeenCalledTimes(6); | ||
}); | ||
}); | ||
@@ -696,0 +785,0 @@ |
@@ -1,2 +0,2 @@ | ||
import { Observable, of } from 'rxjs'; | ||
import { empty, merge, Observable, of, Subject } from 'rxjs'; | ||
import { delay, finalize, shareReplay, tap } from 'rxjs/operators'; | ||
@@ -7,2 +7,3 @@ | ||
export const globalCacheBusterNotifier = new Subject<void>(); | ||
export type ICacheRequestResolver = ( | ||
@@ -66,11 +67,16 @@ oldParameters: Array<any>, | ||
const cacheConfig = _cacheConfig ? _cacheConfig : {}; | ||
if (cacheConfig.cacheBusterObserver) { | ||
/** | ||
* subscribe to the cacheBusterObserver and upon emission, clear all caches | ||
*/ | ||
cacheConfig.cacheBusterObserver.subscribe(_ => { | ||
_cachePairs.length = 0; | ||
_observableCachePairs.length = 0; | ||
}); | ||
} | ||
/** | ||
* subscribe to the globalCacheBuster | ||
* if a custom cacheBusterObserver is passed, subscribe to it as well | ||
* subscribe to the cacheBusterObserver and upon emission, clear all caches | ||
*/ | ||
merge( | ||
globalCacheBusterNotifier.asObservable(), | ||
cacheConfig.cacheBusterObserver ? cacheConfig.cacheBusterObserver : empty() | ||
).subscribe((_) => { | ||
_cachePairs.length = 0; | ||
_observableCachePairs.length = 0; | ||
}); | ||
cacheConfig.cacheResolver = cacheConfig.cacheResolver | ||
@@ -77,0 +83,0 @@ ? cacheConfig.cacheResolver |
{ | ||
"name": "ngx-cacheable", | ||
"version": "1.0.7", | ||
"version": "1.0.8", | ||
"description": "Rx Observable cache decorator", | ||
@@ -5,0 +5,0 @@ "main": "dist/index.js", |
@@ -19,3 +19,3 @@ [![Build Status](https://travis-ci.org/angelnikolov/ngx-cacheable.svg?branch=master)](https://travis-ci.org/angelnikolov/ngx-cacheable) | ||
and use it decorate any class method like: | ||
``` | ||
```ts | ||
@Cacheable() | ||
@@ -30,3 +30,3 @@ getUsers() { | ||
``` | ||
```ts | ||
@Cacheable() | ||
@@ -42,4 +42,31 @@ getUser(id:string) { | ||
## Examples | ||
### Cache Busting | ||
You can achieve it by decorating the cache busting method with the CacheBuster decorator. So you can have one method for fetching and caching data and another, to remove the cache. This is useful when for example you want to add an item to a list and refresh that list afterwards. | ||
```ts | ||
const cacheBuster$ = new Subject<void>(); | ||
export class Service { | ||
@Cacheable({ | ||
cacheBusterObserver: cacheBuster$ | ||
}) | ||
getData() { | ||
///needs to return an Observable | ||
} | ||
@CacheBuster({ | ||
cacheBusterNotifier: cacheBuster$ | ||
}) | ||
saveData() { | ||
///needs to return an Observable | ||
} | ||
} | ||
``` | ||
If you want to globally bust your whole cache (i.e caches of all Cacheable decorators), just import the `globalCacheBusterNotifier` and call `next()` on it, like: | ||
```typescript | ||
import { globalCacheBusterNotifier } from './cacheable.decorator'; | ||
globalCacheBusterNotifier.next(); | ||
``` | ||
## Configuration | ||
``` | ||
```ts | ||
export interface ICacheConfig { | ||
@@ -46,0 +73,0 @@ /** |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
96392
1741
118