48 lines
1.5 KiB
JavaScript
Raw Normal View History

2025-11-11 01:05:13 +01:00
export default class FetchInterceptor {
constructor(logger = null, appState = null, perfMonitor = null) {
this.logger = logger;
this.appState = appState;
this.perfMonitor = perfMonitor;
this.activeRequests = 0;
}
async request(url, options = {}) {
this.activeRequests++;
this.appState?.setState({ isLoading: true });
const startTime = performance.now();
try {
this.logger?.debug(`Fetch START: ${options.method || 'GET'} ${url}`);
const response = await fetch(url, {
...options,
headers: {
'Content-Type': 'application/json',
...options.headers
}
});
const duration = performance.now() - startTime;
this.perfMonitor?.['_recordMetric']?.('fetch', duration);
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
const data = await response.json();
this.logger?.debug(`Fetch SUCCESS: ${url}`, { status: response.status, duration: `${duration.toFixed(2)}ms` });
return data;
} catch (error) {
this.logger?.error(`Fetch FAILED: ${url}`, { error: error.message });
throw error;
} finally {
this.activeRequests--;
if (this.activeRequests === 0) {
this.appState?.setState({ isLoading: false });
}
}
}
}