NcachedService
The single injectable that powers ng-ncached. Provided in 'root', so it's a singleton across the entire application.
import { NcachedService } from 'ng-ncached';
Public methods
| Method | Purpose |
|---|---|
set | Store a value under a key path, optionally with TTL. |
get | Read a value back. Throws on miss / expired. |
getOrDefault | Read a value back, returning a default on miss / expired. Never throws for misses. |
has | Check if a non-expired entry exists at a path. Boolean. Never throws. |
cacheObservable | Cache the result of an Observable, with optional TTL, fallback, and request dedup. |
keys | List every complete key path under an optional prefix. |
size | Count non-expired entries across the cache. |
remove | Delete a single cache entry. No-op on missing path. |
clear | Delete an entire subtree / namespace. No-op on missing path. |
clearAll | Wipe the in-memory cache (and localStorage entry if persistence is on). |
set
set<T = any>(value: T, ...args: Array<string | ISetOptions>): void
Stores value in the cache under the given key path.
value— the value to store. No constraints.args— at least two strings. The last string is theMapkey; everything before it is the namespace path. An optionalISetOptionsobject may be passed as the last argument.- Returns —
void.
Throws
| Error | When |
|---|---|
NcachedServiceErrors.InsufficientsKeysProvidedError | Fewer than two string keys were passed |
NcachedServiceErrors.UncloneableValueError | The value cannot be deep-cloned by structuredClone (functions, DOM nodes, etc.) |
Cloning — since v1.1.0, set() deep-clones the value before storing it via structuredClone. Mutating your source object after the call does not affect the cached value.
Example
this._cache.set<string>('Hello', 'app', 'greeting');
this._cache.set<IUser>(user, 'users', 'byId', user.id);
this._cache.set<string>(token, 'auth', 'token', { ttl: 60_000 });
See Setting values and TTL & expiration.
get
get<T = any>(...keys: string[]): T
Reads a value out of the cache using the same key path it was stored under.
keys— at least two strings. Must match a path used in a previousset().T— the expected type of the returned value. Strongly recommended.- Returns — the cached value, typed as
T.
Throws
| Error | When |
|---|---|
NcachedServiceErrors.InsufficientsKeysProvidedError | Fewer than two keys were passed |
NcachedServiceErrors.KeyNotFound | A namespace key in the path doesn't exist |
NcachedServiceErrors.MapNotFound | A key in the path exists but doesn't point to a Map |
NcachedServiceErrors.ValueNotFound | The map entry is missing or the entry has expired (TTL) |
NcachedServiceErrors.UncloneableValueError | The cached value cannot be deep-cloned by structuredClone |
When an entry is expired, it is removed from the underlying Map before throwing.
Cloning — since v1.1.0, get() returns a deep clone of the cached value via structuredClone. Mutating the returned object does not affect the cache, and two consecutive get() calls produce two independent copies.
Example
const greeting = this._cache.get<string>('app', 'greeting');
const user = this._cache.get<IUser>('users', 'byId', 'usr_42');
See Getting values.
getOrDefault
getOrDefault<T = any>(defaultValue: T, ...keys: string[]): T
Reads a value, returning defaultValue if the entry is missing or expired. Never throws for cache misses.
defaultValue— fallback returned on any cache miss.keys— same rules asget().- Returns — the cached value or
defaultValue.
Example
const theme = this._cache.getOrDefault<string>('light', 'ui', 'theme');
This is the safe, ergonomic accessor — prefer it over wrapping get() in a try/catch.
has
has(...keys: string[]): boolean
Returns true if a non-expired entry exists at the given path, false otherwise. Never throws — invalid call shapes (fewer than 2 keys), missing paths, and expired entries all return false.
keys— same rules asget(). Min 2.
Pure read — has() does not delete expired entries it encounters. If you want lazy cleanup of expired entries as a side effect, use get() (which throws and deletes) or getOrDefault() (which deletes silently).
Example
this._cache.set('Ada', 'users', 'currentName');
this._cache.has('users', 'currentName'); // true
this._cache.has('users', 'missing'); // false
cacheObservable
cacheObservable<T = any>(
source: Observable<T>,
options: ICacheObservableOptions<T>,
...keys: string[]
): Observable<T>
Caches the result of an Observable source. On cache hit, emits the cached value via of() without subscribing to the source. On cache miss, subscribes to source, stores the emitted value (with optional TTL), and emits it.
source— the upstream observable, typically anHttpClientcall.options—{ ttl?: number; defaultValue?: T }. SeeICacheObservableOptions.keys— same key path rules asget/set. Min 2.- Returns — an
Observable<T>that emits exactly once.
Behaviour
- Concurrent calls with the same keys share one subscription via
shareReplay({ bufferSize: 1, refCount: true }). The in-flight entry is keyed bykeys.join('::')and cleaned up on completion or error. - Source error +
defaultValueprovided → emitsdefaultValue. - Source error, no
defaultValue→ re-throws.
Example
this._cache.cacheObservable<IUser[]>(
this._http.get<IUser[]>('/api/users'),
{ ttl: 30_000 },
'api', 'users',
).subscribe(users => console.log(users));
See Caching observables.
remove
remove(...keys: string[]): void
Removes a single cache entry. The last key is the Map key; preceding keys navigate the hierarchy. No-op if the path or key does not exist. Does not throw.
Example
this._cache.remove('users', 'currentName');
this._cache.remove('nonexistent', 'key'); // no-op
If fewer than two keys are passed, the call is a no-op (no exception).
clear
clear(...keys: string[]): void
Removes an entire subtree from the cache. Calling with one key drops a top-level namespace; calling with N keys drops the deepest node at that path. No-op on missing paths.
Example
this._cache.clear('users'); // drops all 'users'
this._cache.clear('users', 'byOrg', 'org-1'); // drops org-1 only
this._cache.clear(); // no-op (use clearAll() to wipe)
clearAll
clearAll(): void
Wipes the entire in-memory cache. If persistence is enabled, also removes the configured localStorage entry. The localStorage removal is best-effort — if it fails, the in-memory cache is still cleared.
Example
this._cache.clearAll();
keys
keys(...prefix: string[]): string[][]
Lists every complete key path under the given prefix. Each returned path is a full key chain (prefix + leaf), suitable for direct use with get/set/remove. Expired entries are skipped (without being deleted). Returns an empty array when the prefix doesn't exist.
prefix— optional namespace prefix to scope the listing. Pass nothing to list every path.
Example
this._cache.set('Ada', 'users', 'byOrg', 'org-1', 'u1');
this._cache.set('Alan', 'users', 'byOrg', 'org-1', 'u2');
this._cache.set('Bob', 'users', 'byOrg', 'org-2', 'u1');
this._cache.keys('users', 'byOrg', 'org-1');
// [['users', 'byOrg', 'org-1', 'u1'], ['users', 'byOrg', 'org-1', 'u2']]
this._cache.keys(); // every path in the cache
size
size(): number
Returns the total count of non-expired entries across the entire cache. Pure read — does not delete the expired entries it skips during traversal.
Example
this._cache.set('a', 'mod', 'k1');
this._cache.set('b', 'mod', 'k2');
this._cache.set('c', 'other', 'k1', 'k2');
this._cache.size(); // 3
Constructor
constructor(@Optional() @Inject(NCACHED_CONFIG) config: INcachedConfig | null)
You don't call this directly — Angular's DI does. If provideNcachedConfig() is in the providers, the resolved config is injected; otherwise null is used and the service runs in pure in-memory mode.
When config.persistence.enabled is true, the constructor:
- Calls
_hydrate()— readslocalStorage, decompresses, deserialises, drops expired entries. - Registers a
beforeunloadlistener that calls_persist().
Lifecycle and scope
NcachedService is providedIn: 'root', so:
- It's a singleton across the whole app.
- The internal cache lives in memory for the duration of the page session — and across reloads if persistence is enabled.
- There's no built-in cross-tab synchronisation.
For multiple isolated cache instances (e.g. per feature), provide NcachedService at a lower injector level.