feat(map): add event-driven GPS update

This commit is contained in:
Lê Tuấn Anh
2025-11-20 09:05:07 +07:00
parent eed98f7c29
commit dea435a4ec
11 changed files with 333 additions and 159 deletions

30
src/utils/cacheStore.ts Normal file
View File

@@ -0,0 +1,30 @@
// src/utils/cacheStore.ts
interface CacheItem<T> {
data: T;
timestamp: number;
}
const TTL = 1 * 1000; // dữ liệu có hiệu lực trong 1 giây để GPS realtime
const cache: Record<string, CacheItem<any>> = {};
export function getCache<T>(key: string): T | null {
const item = cache[key];
if (!item) return null;
if (Date.now() - item.timestamp > TTL) {
delete cache[key];
return null;
}
return item.data;
}
export function setCache<T>(key: string, data: T) {
cache[key] = { data, timestamp: Date.now() };
}
export function invalidate(key: string) {
delete cache[key];
}
export function getAllCacheKeys(): string[] {
return Object.keys(cache);
}

24
src/utils/eventBus.ts Normal file
View File

@@ -0,0 +1,24 @@
// src/utils/eventBus.ts
type EventHandler<T = any> = (data: T) => void;
class EventBus {
private listeners: Record<string, EventHandler[]> = {};
on(event: string, handler: EventHandler) {
if (!this.listeners[event]) this.listeners[event] = [];
this.listeners[event].push(handler);
}
off(event: string, handler: EventHandler) {
this.listeners[event] = (this.listeners[event] || []).filter(
(h) => h !== handler,
);
}
emit(event: string, data?: any) {
(this.listeners[event] || []).forEach((h) => h(data));
}
}
// ✅ phải có dòng này
export const eventBus = new EventBus();

View File

@@ -0,0 +1,27 @@
// utils/queryWithCache.ts
import { getCache, setCache, invalidate, getAllCacheKeys } from './cacheStore';
import { eventBus } from './eventBus';
export async function queryWithCache<T>(
key: string,
fetcher: () => Promise<T>,
): Promise<T> {
const cached = getCache<T>(key);
if (cached) return cached;
const data = await fetcher();
setCache(key, data);
// Phát sự kiện để các component khác biết có data mới
eventBus.emit(`${key}:update`, data);
return data;
}
// Xóa cache theo key hoặc prefix
queryWithCache.clear = (prefix = '') => {
const keys = getAllCacheKeys();
for (const key of keys) {
if (key.startsWith(prefix)) invalidate(key);
}
};