W kosmosie rzeczy często nie ida zgodnie z planem - komunikacja może byc przerwana, serwery moga byc przeciazone, dane moga byc uszkodzone. Dobra obsługa błędów to różnica między udana misja a katastrofa!
1async function fetchWithFullErrorHandling(url) {
2 try {
3 // Proba pobrania danych
4 const response = await fetch(url);
5
6 if (!response.ok) {
7 // Rozne komunikaty dla różnych kodow błędów
8 switch (response.status) {
9 case 400:
10 throw new Error('Nieprawidlowe zapytanie');
11 case 401:
12 throw new Error('Brak autoryzacji - zaloguj sie');
13 case 403:
14 throw new Error('Brak dostepu do tego zasobu');
15 case 404:
16 throw new Error('Zasob nie zostal znaleziony');
17 case 429:
18 throw new Error('Zbyt wiele zapytan - sprobuj pozniej');
19 case 500:
20 throw new Error('Błąd serwera - spróbuj później');
21 default:
22 throw new Error(\`Nieznany błąd: \${response.status}\`);
23 }
24 }
25
26 return await response.json();
27 } catch (err) {
28 // Obsluga błędów sieci (brak internetu, timeout)
29 if (err instanceof TypeError) {
30 throw new Error(
31 'Błąd sieci - sprawdź połączenie z internetem'
32 );
33 }
34 throw err; // Re-throw inne błędy
35 }
36}React oferuje Error Boundaries - komponenty, które lapią błędy renderowania w swoich dzieciach:
1import React from 'react';
2
3class ErrorBoundary extends React.Component {
4 constructor(props) {
5 super(props);
6 this.state = { hasError: false, error: null };
7 }
8
9 static getDerivedStateFromError(error) {
10 return { hasError: true, error };
11 }
12
13 componentDidCatch(error, errorInfo) {
14 console.error('ErrorBoundary złapał błąd:', error);
15 console.error('Stack:', errorInfo.componentStack);
16 }
17
18 render() {
19 if (this.state.hasError) {
20 return (
21 <div className="error-boundary">
22 <h2>Cos poszlo nie tak</h2>
23 <p>{this.state.error?.message}</p>
24 <button onClick={() => this.setState({
25 hasError: false, error: null
26 })}>
27 Sprobuj ponownie
28 </button>
29 </div>
30 );
31 }
32
33 return this.props.children;
34 }
35}
36
37// Uzycie:
38function App() {
39 return (
40 <ErrorBoundary>
41 <SpaceDashboard />
42 </ErrorBoundary>
43 );
44}Zamiast wyswietlac błędy w miejscu komponentu, można użyć powiadomien toast:
1import React, { useState, createContext, useContext } from 'react';
2
3const ToastContext = createContext();
4
5function ToastProvider({ children }) {
6 const [toasts, setToasts] = useState([]);
7
8 const addToast = (message, type = 'error') => {
9 const id = Date.now();
10 setToasts(prev => [...prev, { id, message, type }]);
11 // Auto-usuwanie po 5 sekundach
12 setTimeout(() => {
13 setToasts(prev => prev.filter(t => t.id !== id));
14 }, 5000);
15 };
16
17 return (
18 <ToastContext.Provider value={{ addToast }}>
19 {children}
20 <div className="toast-container">
21 {toasts.map(toast => (
22 <div key={toast.id} className={\`toast toast-\${toast.type}\`}>
23 {toast.message}
24 </div>
25 ))}
26 </div>
27 </ToastContext.Provider>
28 );
29}
30
31function useToast() {
32 return useContext(ToastContext);
33}
34
35// Uzycie w komponencie:
36function DataComponent() {
37 const { addToast } = useToast();
38
39 const fetchData = async () => {
40 try {
41 const response = await fetch('/api/data');
42 if (!response.ok) throw new Error('Blad serwera');
43 const data = await response.json();
44 addToast('Dane pobrane pomyslnie!', 'success');
45 } catch (err) {
46 addToast(err.message, 'error');
47 }
48 };
49
50 return <button onClick={fetchData}>Pobierz dane</button>;
51}Gdy serwer jest przeciazony, warto czekac coraz dłużej między kolejnymi probami:
1async function fetchWithRetry(url, maxRetries = 3) {
2 for (let attempt = 0; attempt <= maxRetries; attempt++) {
3 try {
4 const response = await fetch(url);
5
6 if (response.status === 429 || response.status >= 500) {
7 // Serwer przeciazony lub błąd serwera
8 if (attempt < maxRetries) {
9 // Exponential backoff: 1s, 2s, 4s
10 const delay = Math.pow(2, attempt) * 1000;
11 console.log(
12 \`Proba \${attempt + 1} nie powiodla sie. \
13Ponowna proba za \${delay}ms...\`
14 );
15 await new Promise(resolve =>
16 setTimeout(resolve, delay)
17 );
18 continue;
19 }
20 }
21
22 if (!response.ok) {
23 throw new Error(\`HTTP Error: \${response.status}\`);
24 }
25
26 return await response.json();
27 } catch (err) {
28 if (attempt === maxRetries) {
29 throw new Error(
30 \`Nie udalo sie po \${maxRetries + 1} probach: \${err.message}\`
31 );
32 }
33
34 const delay = Math.pow(2, attempt) * 1000;
35 await new Promise(resolve => setTimeout(resolve, delay));
36 }
37 }
38}Wyrazny feedback o błędach i mechanizmy naprawy to klucz do swietnego doświadczenia użytkownika. Nigdy nie zostawiaj użytkownika bez informacji o tym, co poszlo nie tak i co może zrobic!