File size: 3,796 Bytes
b190b45 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 |
/**
* API Client Error Handling Fix
* Add this to your api-client.js file
*/
class APIClient {
constructor(baseURL = '') {
this.baseURL = baseURL;
this.errors = [];
}
/**
* Fixed error handling with proper null checks
*/
_getFallbackData(error) {
// Ensure error is an object
const safeError = error || {};
return {
data: [],
success: false,
error: true,
message: safeError.message || 'Failed to fetch data',
timestamp: Date.now(),
details: {
name: safeError.name || 'Error',
stack: safeError.stack || 'No stack trace available'
}
};
}
/**
* Fixed error logging with proper null checks
*/
_logError(endpoint, method, error, duration = 0) {
const errorLog = {
endpoint: endpoint || 'unknown',
method: method || 'GET',
message: error?.message || 'Unknown error',
duration: duration,
timestamp: new Date().toISOString()
};
this.errors.push(errorLog);
console.error('[APIClient] Error logged:', errorLog);
// Keep only last 50 errors
if (this.errors.length > 50) {
this.errors = this.errors.slice(-50);
}
}
/**
* Fixed request method with comprehensive error handling
*/
async request(endpoint, options = {}) {
const startTime = Date.now();
const method = options.method || 'GET';
try {
const url = endpoint.startsWith('http')
? endpoint
: `${this.baseURL}${endpoint}`;
const response = await fetch(url, {
...options,
headers: {
'Content-Type': 'application/json',
...options.headers
}
});
const duration = Date.now() - startTime;
if (!response.ok) {
const errorText = await response.text().catch(() => 'No error message');
const error = new Error(`HTTP ${response.status}: ${errorText}`);
error.status = response.status;
error.statusText = response.statusText;
this._logError(endpoint, method, error, duration);
// Return fallback data instead of throwing
return this._getFallbackData(error);
}
const data = await response.json();
return data;
} catch (error) {
const duration = Date.now() - startTime;
// Handle different error types
const safeError = error || new Error('Unknown error');
if (safeError.name === 'AbortError') {
safeError.message = 'Request timeout';
} else if (!safeError.message) {
safeError.message = 'Network error or invalid response';
}
this._logError(endpoint, method, safeError, duration);
// Return fallback data instead of throwing
return this._getFallbackData(safeError);
}
}
/**
* GET request wrapper
*/
async get(endpoint, options = {}) {
return this.request(endpoint, { ...options, method: 'GET' });
}
/**
* POST request wrapper
*/
async post(endpoint, data, options = {}) {
return this.request(endpoint, {
...options,
method: 'POST',
body: JSON.stringify(data)
});
}
/**
* PUT request wrapper
*/
async put(endpoint, data, options = {}) {
return this.request(endpoint, {
...options,
method: 'PUT',
body: JSON.stringify(data)
});
}
/**
* DELETE request wrapper
*/
async delete(endpoint, options = {}) {
return this.request(endpoint, { ...options, method: 'DELETE' });
}
/**
* Get error history
*/
getErrors() {
return [...this.errors];
}
/**
* Clear error history
*/
clearErrors() {
this.errors = [];
}
}
// Export singleton instance
export const api = new APIClient('/api');
export default api;
|