Gids voor het implementeren van een robuuste foutafhandelingsstrategie in mijn TypeScript-toepassing voor {{fout_scenario}}.
description
Door deze gids te volgen, verbeter je de stabiliteit van je toepassing, verhoog je de gebruikerservaring door duidelijke foutmeldingen te bieden en zorg je ervoor dat fouten correct worden gelogd en afgehandeld.
prompt
try_prompt
Help me bij het ontwikkelen van een uitgebreide foutafhandelingsstrategie in mijn TypeScript-toepassing voor {{fout_scenario}}. Geef gedetailleerde stappen, ... more
generate_helper
...
tags
ai_answers
provider: openai
model: gpt-4.1-nano
Natuurlijk! Een uitgebreide foutafhandelingsstrategie voor API-aanroepen in je TypeScript-toepassing is essentieel om stabiliteit en gebruiksvriendelijkheid te waarborgen. Hieronder vind je gedetailleerde stappen, codevoorbeelden en best practices:
**1. Structureren van API-aanroepen met try-catch en async/await**
Gebruik async/await voor leesbaarheid en eenvoudige foutafhandeling met try-catch blokken.
```typescript
async function fetchData(url: string): Promise<any> {
try {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`HTTP-fout: ${response.status} ${response.statusText}`);
}
const data = await response.json();
return data;
} catch (error) {
// Fout wordt hier opgevangen
handleError(error);
// eventueel teruggeven van een standaardwaarde of opnieuw proberen
return null;
}
}
```
**2. Implementeren van een centrale foutafhandelingsfunctie**
Maak een functie die alle fouten afhandelt en logt, zodat consistentie wordt gewaarborgd.
```typescript
function handleError(error: any): void {
// Log de fout naar de console
console.error('API-fout:', error);
// Optioneel: log naar externe monitoringtools
// logToExternalService(error);
// Geef gebruikersvriendelijke feedback
showUserErrorMessage('Er is een fout opgetreden bij het ophalen van gegevens. Probeer het later opnieuw.');
}
```
**3. Gebruiken van logging en monitoring**
Integreer logging naar externe diensten zoals Sentry, LogRocket, of een eigen loggingserver om fouten te traceren.
```typescript
function logToExternalService(error: any): void {
// Voorbeeld met Sentry
// Sentry.captureException(error);
}
```
**4. Gebruikersvriendelijke foutmeldingen**
Laat gebruikers weten dat er een probleem is, zonder technische details te tonen.
```typescript
function showUserErrorMessage(message: string): void {
// Bijvoorbeeld via een modal, toast of statusbalk
alert(message); // of gebruik een toast component
}
```
**5. Herstel- en retry-strategieën**
Voor kritieke API-aanroepen kun je retries implementeren met backoff:
```typescript
async function fetchWithRetry(url: string, retries = 3, delayMs = 1000): Promise<any> {
for (let attempt = 1; attempt <= retries; attempt++) {
try {
const data = await fetchData(url);
if (data !== null) {
return data;
}
} catch (error) {
// Fout wordt afgehandeld in fetchData
}
// Wacht voordat je opnieuw probeert
await new Promise(res => setTimeout(res, delayMs * attempt));
}
showUserErrorMessage('Kon gegevens niet ophalen. Probeer het later opnieuw.');
return null;
}
```
**6. TypeScript-specifieke best practices**
- Gebruik `unknown` voor error types en type correcties:
```typescript
function handleError(error: unknown): void {
if (error instanceof Error) {
console.error('Fout:', error.message);
} else {
console.error('Onbekende fout:', error);
}
}
```
- Definieer types voor API-responses en fouten om typeveiligheid te vergroten.
**7. Foutafhandeling in componenten en services**
Zorg dat foutafhandeling niet alleen in data-fetching gebeurt, maar ook in UI-componenten en services, zodat gebruikers duidelijk geïnformeerd worden en de app niet crasht.
**8. Testen van foutscenario’s**
Gebruik mocks en simulaties om te testen hoe je applicatie reageert op verschillende foutscenario’s, bijvoorbeeld door API-responses met foutcodes of netwerkfouten te simuleren.
---
**Samenvatting:**
- Gebruik async/await met try-catch
- Centraliseer foutafhandeling in een `handleError` functie
- Log fouten naar console en externe monitoring
- Toon gebruiksvriendelijke foutmeldingen
- Implementeer retries met backoff
- Gebruik TypeScript-typen voor errors en responses
- Test je foutafhandelingsmechanismen uitgebreid
Door deze stappen te volgen, wordt je toepassing niet alleen stabieler, maar ook beter in staat om fouten te detecteren, te loggen en gebruikers vriendelijk te informeren.
provider: deepseek
model: deepseek-chat
Zeker! Hier is een uitgebreide foutafhandelingsstrategie voor TypeScript API-aanroepen:
## 1. Basis Foutklassen Structuur
```typescript
// errors/custom-errors.ts
export abstract class CustomError extends Error {
abstract statusCode: number;
abstract isOperational: boolean;
constructor(message: string) {
super(message);
this.name = this.constructor.name;
this.isOperational = true;
Error.captureStackTrace(this, this.constructor);
}
abstract serializeErrors(): { message: string; field?: string }[];
}
export class APIError extends CustomError {
statusCode: number;
isOperational: boolean;
constructor(
message: string,
statusCode: number = 500,
isOperational: boolean = true
) {
super(message);
this.statusCode = statusCode;
this.isOperational = isOperational;
}
serializeErrors() {
return [{ message: this.message }];
}
}
export class ValidationError extends CustomError {
statusCode = 400;
constructor(public errors: { field: string; message: string }[]) {
super("Validatiefout opgetreden");
}
serializeErrors() {
return this.errors;
}
}
export class NotFoundError extends CustomError {
statusCode = 404;
constructor(resource: string = "Resource") {
super(`${resource} niet gevonden`);
}
serializeErrors() {
return [{ message: this.message }];
}
}
```
## 2. Gestandaardiseerde API Response
```typescript
// types/api-types.ts
export interface ApiResponse<T = any> {
success: boolean;
data?: T;
error?: {
message: string;
code?: string;
details?: any[];
};
timestamp: string;
}
export interface ApiErrorResponse {
success: false;
error: {
message: string;
code: string;
details?: any[];
};
timestamp: string;
}
```
## 3. HTTP Client met Foutafhandeling
```typescript
// services/http-client.ts
import { APIError, NotFoundError, ValidationError } from '../errors/custom-errors';
import { ApiResponse } from '../types/api-types';
class HttpClient {
private baseURL: string;
private defaultHeaders: HeadersInit;
constructor(baseURL: string) {
this.baseURL = baseURL;
this.defaultHeaders = {
'Content-Type': 'application/json',
};
}
private async handleResponse<T>(response: Response): Promise<T> {
if (!response.ok) {
const errorData = await response.json().catch(() => ({
message: response.statusText
}));
switch (response.status) {
case 400:
throw new ValidationError(errorData.errors || []);
case 404:
throw new NotFoundError(errorData.resource);
case 429:
throw new APIError('Te veel requests', 429);
case 500:
throw new APIError('Interne serverfout', 500);
default:
throw new APIError(
errorData.message || `HTTP Error: ${response.status}`,
response.status
);
}
}
return response.json();
}
async get<T>(endpoint: string, options?: RequestInit): Promise<T> {
const response = await fetch(`${this.baseURL}${endpoint}`, {
method: 'GET',
headers: { ...this.defaultHeaders, ...options?.headers },
...options,
});
return this.handleResponse<T>(response);
}
async post<T>(endpoint: string, data?: any, options?: RequestInit): Promise<T> {
const response = await fetch(`${this.baseURL}${endpoint}`, {
method: 'POST',
headers: { ...this.defaultHeaders, ...options?.headers },
body: data ? JSON.stringify(data) : undefined,
...options,
});
return this.handleResponse<T>(response);
}
// Vergelijkbare methoden voor PUT, PATCH, DELETE...
}
export const httpClient = new HttpClient(process.env.API_BASE_URL || '');
```
## 4. Geavanceerde Logging Service
```typescript
// services/logger.ts
export enum LogLevel {
ERROR = 'error',
WARN = 'warn',
INFO = 'info',
DEBUG = 'debug'
}
export class Logger {
private logToConsole(level: LogLevel, message: string, meta?: any) {
const timestamp = new Date().toISOString();
const logEntry = { timestamp, level, message, ...meta };
switch (level) {
case LogLevel.ERROR:
console.error(JSON.stringify(logEntry));
break;
case LogLevel.WARN:
console.warn(JSON.stringify(logEntry));
break;
case LogLevel.INFO:
console.info(JSON.stringify(logEntry));
break;
default:
console.log(JSON.stringify(logEntry));
}
// Stuur kritieke errors naar externe service
if (level === LogLevel.ERROR) {
this.sendToErrorReporting(logEntry);
}
}
private async sendToErrorReporting(logEntry: any) {
try {
// Integratie met Sentry, LogRocket, etc.
if (process.env.NODE_ENV === 'production') {
await fetch('/api/logs', {
method: 'POST',
body: JSON.stringify(logEntry),
});
}
} catch (error) {
console.error('Failed to send error to reporting service:', error);
}
}
error(message: string, error?: Error, meta?: any) {
this.logToConsole(LogLevel.ERROR, message, {
error: error?.message,
stack: error?.stack,
...meta
});
}
warn(message: string, meta?: any) {
this.logToConsole(LogLevel.WARN, message, meta);
}
info(message: string, meta?: any) {
this.logToConsole(LogLevel.INFO, message, meta);
}
debug(message: string, meta?: any) {
if (process.env.NODE_ENV === 'development') {
this.logToConsole(LogLevel.DEBUG, message, meta);
}
}
}
export const logger = new Logger();
```
## 5. React Hook voor API Calls
```typescript
// hooks/useApi.ts
import { useState, useCallback } from 'react';
import { httpClient } from '../services/http-client';
import { logger } from '../services/logger';
import { APIError } from '../errors/custom-errors';
interface UseApiState<T> {
data: T | null;
loading: boolean;
error: string | null;
}
export function useApi<T>() {
const [state, setState] = useState<UseApiState<T>>({
data: null,
loading: false,
error: null,
});
const execute = useCallback(async (
apiCall: () => Promise<T>,
options?: { showError?: boolean }
) => {
setState(prev => ({ ...prev, loading: true, error: null }));
try {
const data = await apiCall();
setState({ data, loading: false, error: null });
return data;
} catch (error) {
const errorMessage = error instanceof APIError
? error.message
: 'Er is een onverwachte fout opgetreden';
logger.error('API call failed', error, {
showError: options?.showError
});
setState(prev => ({
...prev,
loading: false,
error: errorMessage
}));
// Toon gebruikersvriendelijke melding indien gewenst
if (options?.showError) {
// Gebruik toast notification of andere UI feedback
showUserNotification(errorMessage, 'error');
}
throw error;
}
}, []);
const reset = useCallback(() => {
setState({ data: null, loading: false, error: null });
}, []);
return { ...state, execute, reset };
}
```
## 6. Gebruik in Components
```typescript
// components/UserProfile.tsx
import React from 'react';
import { useApi } from '../hooks/useApi';
import { httpClient } from '../services/http-client';
interface User {
id: string;
name: string;
email: string;
}
export function UserProfile({ userId }: { userId: string }) {
const { data: user, loading, error, execute } = useApi<User>();
const fetchUser = async () => {
try {
await execute(
() => httpClient.get<User>(`/users/${userId}`),
{ showError: true } // Toon foutmelding aan gebruiker
);
} catch (error) {
// Fout is al afgehandeld in de hook
}
};
React.useEffect(() => {
fetchUser();
}, [userId]);
if (loading) return <div>Laden...</div>;
if (error) return <div className="error">{error}</div>;
if (!user) return <div>Geen gebruiker gevonden</div>;
return (
<div>
<h1>{user.name}</h1>
<p>{user.email}</p>
</div>
);
}
```
## 7. Global Error Boundary (React)
```typescript
// components/ErrorBoundary.tsx
import React from 'react';
import { logger } from '../services/logger';
interface State {
hasError: boolean;
error?: Error;
}
export class ErrorBoundary extends React.Component<
{ children: React.ReactNode; fallback?: React.ReactNode },
State
> {
constructor(props: any) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError(error: Error): State {
return { hasError: true, error };
}
componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {
logger.error('React Error Boundary caught an error', error, {
componentStack: errorInfo.componentStack
});
}
render() {
if (this.state.hasError) {
return this.props.fallback || (
<div className="error-boundary">
<h2>Er is iets misgegaan</h2>
<p>Probeer de pagina te vernieuwen of contacteer support.</p>
<button onClick={() => this.setState({ hasError: false })}>
Opnieuw proberen
</button>
</div>
);
}
return this.props.children;
}
}
```
## 8. Retry Mechanisme met Exponential Backoff
```typescript
// utils/retry.ts
export async function retry<T>(
operation: () => Promise<T>,
maxRetries: number = 3,
delay: number = 1000
): Promise<T> {
let lastError: Error;
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
return await operation();
} catch (error) {
lastError = error as Error;
if (attempt === maxRetries) break;
// Wacht exponentieel langer bij elke poging
const waitTime = delay * Math.pow(2, attempt - 1);
await new Promise(resolve => setTimeout(resolve, waitTime));
}
}
throw lastError!;
}
```
## Best Practices Samenvatting:
1. **Gebruik gestandaardiseerde error classes** voor consistente foutafhandeling
2. **Implementeer verschillende log levels** voor ontwikkel- en productieomgeving
3. **Toon gebruikersvriendelijke berichten** maar log technische details
4. **Gebruik React Error Boundaries** voor onverwachte UI fouten
5. **Implementeer retry logic** voor tijdelijke netwerkfouten
6. **Monitor API performance** en foutpercentages
7. **Valideer responses** met TypeScript interfaces/zod schema's
8. **Gebruik circuit breakers** bij herhaalde API falen
Deze strategie zorgt voor robuuste foutafhandeling, duidelijke logging en een goede gebruikerservaring, zelfs wanneer API calls falen.
error: Generation failed [deepseek] prompt_id=17630 locale=es err=DeepSeek connection/timeout

