Skip to main content

Invalidation

Three methods cover everything from "drop a single entry" to "wipe the world": remove, clear, clearAll. All are no-ops on missing paths — they never throw.

At a glance

MethodScopeNo-op on missing path?
remove(...keys)One entry inside a Map
clear(...keys)An entire namespace / subtree
clearAll()Everything (also localStorage if enabled)n/a

remove(...keys)

Removes a single cache entry. Same key-path semantics as get() / set(): the last key is the Map entry key; everything before it navigates the hierarchy.

this._cache.set('val1', 'users', 'currentName');
this._cache.set('val2', 'users', 'lastSeen');

this._cache.remove('users', 'currentName');

this._cache.get<string>('users', 'lastSeen'); // 'val2' — survives
this._cache.getOrDefault<string>('—', 'users', 'currentName'); // '—'

Calling remove() with fewer than two keys is a no-op. Calling it on a path that doesn't exist is also a no-op:

this._cache.remove('nope', 'still-nope'); // does nothing, doesn't throw

clear(...keys)

Removes an entire subtree — useful when you've invalidated a whole module or tenant.

this._cache.set('a', 'users', 'byOrg', 'org-1', 'u1');
this._cache.set('b', 'users', 'byOrg', 'org-1', 'u2');
this._cache.set('c', 'users', 'byOrg', 'org-2', 'u1');

// Drop everything for org-1
this._cache.clear('users', 'byOrg', 'org-1');

this._cache.getOrDefault('—', 'users', 'byOrg', 'org-1', 'u1'); // '—'
this._cache.get<string>('users', 'byOrg', 'org-2', 'u1'); // 'c' — survives

Calling clear() with one key drops a whole top-level namespace:

this._cache.clear('users'); // removes the entire 'users' branch

Calling clear() with no keys is a no-op (it does not wipe the cache — use clearAll() for that).

clearAll()

Wipes the entire in-memory cache. If persistence is enabled, the localStorage entry is removed too.

this._cache.set('a', 'mod1', 'key');
this._cache.set('b', 'mod2', 'key');

this._cache.clearAll();

this._cache.getOrDefault('—', 'mod1', 'key'); // '—'

Use it for sign-out flows, "switch account" actions, or after a global config change.

Real-world example: invalidation on user logout

import { Injectable, inject } from '@angular/core';
import { Router } from '@angular/router';
import { NcachedService } from 'ng-ncached';

@Injectable({ providedIn: 'root' })
export class SessionService {
private readonly _cache = inject(NcachedService);
private readonly _router = inject(Router);

logout(): void {
this._cache.clearAll();
this._router.navigate(['/login']);
}
}

Real-world example: targeted invalidation after a mutation

When a write succeeds on the server, drop the cached read for that resource so the next call refetches:

import { HttpClient } from '@angular/common/http';
import { Injectable, inject } from '@angular/core';
import { Observable, tap } from 'rxjs';
import { NcachedService } from 'ng-ncached';

interface IUser {
email: string;
id: string;
name: string;
}

@Injectable({ providedIn: 'root' })
export class UserService {
private readonly _cache = inject(NcachedService);
private readonly _http = inject(HttpClient);

updateUser(user: IUser): Observable<IUser> {
return this._http.put<IUser>(`/api/users/${user.id}`, user).pipe(
tap(() => this._cache.remove('api', 'users', user.id)),
);
}
}

If a single write affects an entire collection, clear the namespace instead of removing one entry:

this._cache.clear('api', 'users');

TTL vs explicit invalidation

Use casePrefer
Data is expensive to fetch but acceptably stale for N secondsTTL via set()
Data is invalidated by a specific action (write, logout, settings)remove/clear

The two compose well — set a generous TTL as a safety net, and explicitly invalidate on known mutations.

What's next?