54 lines
1.5 KiB
TypeScript
54 lines
1.5 KiB
TypeScript
import { Injectable } from '@angular/core';
|
|
|
|
// Cache expiration time. (In a real shop this should not be the beast approach due to stock changes)
|
|
const CACHE_TTL_MS = 60 * 60 * 1000;
|
|
|
|
// Prefix for cache keys to avoid collisions with other localStorage entries.
|
|
const CACHE_PREFIX = 'itx-cache:';
|
|
|
|
interface CacheEntry<T> {
|
|
timestamp: number;
|
|
data: T;
|
|
}
|
|
|
|
// Generic cache service
|
|
@Injectable({ providedIn: 'root' })
|
|
export class CacheService {
|
|
// returns cached item if it exists and is not expired, otherwise fetches it using the provided fetcher function.
|
|
async getOrFetch<T>(key: string, fetcher: () => Promise<T>): Promise<T> {
|
|
const cached = this.read<T>(key);
|
|
if (cached && Date.now() - cached.timestamp < CACHE_TTL_MS) {
|
|
return cached.data;
|
|
}
|
|
|
|
const data = await fetcher();
|
|
this.write(key, data);
|
|
return data;
|
|
}
|
|
|
|
// Clears all cache entries managed by this service.
|
|
clear(): void {
|
|
Object.keys(localStorage)
|
|
.filter((key) => key.startsWith(CACHE_PREFIX))
|
|
.forEach((key) => localStorage.removeItem(key));
|
|
}
|
|
|
|
private read<T>(key: string): CacheEntry<T> | null {
|
|
const raw = localStorage.getItem(CACHE_PREFIX + key);
|
|
if (!raw) {
|
|
return null;
|
|
}
|
|
try {
|
|
return JSON.parse(raw) as CacheEntry<T>;
|
|
} catch {
|
|
// corrupted data
|
|
return null;
|
|
}
|
|
}
|
|
|
|
private write<T>(key: string, data: T): void {
|
|
const entry: CacheEntry<T> = { timestamp: Date.now(), data };
|
|
localStorage.setItem(CACHE_PREFIX + key, JSON.stringify(entry));
|
|
}
|
|
}
|