Student starter code (30% baseline)
index.html- Main HTML pagescript.js- JavaScript logicstyles.css- Styling and layoutpackage.json- Dependenciessetup.sh- Setup scriptREADME.md- Instructions (below)💡 Download the ZIP, extract it, and follow the instructions below to get started!
Welcome to the most important skill in production API development: building resilient applications that gracefully handle failures!
By completing this activity, you will:
IMPORTANT: This template includes WORKING error handling patterns! Test them immediately:
# Mac/Linux:
python3 -m http.server 8002
# Windows:
python -m http.server 8002
# Alternative using Node.js:
npx http-server -p 8002
70% of the code is implemented for you:
Complete the retry logic in makeRequestWithRetry() function.
Requirements:
Success Criteria:
Hint: Check the isRetryableError() function for error classification
Implement the circuit breaker to prevent cascading failures.
Circuit Breaker States:
Requirements:
Success Criteria:
Hint: Study circuitBreakerState object and isCircuitBreakerOpen() function
Add a dashboard to track API health and recovery patterns.
Features to Build:
Success Criteria:
Hint: Use stats object and circuitBreakerState for data source
Complete the four pattern demonstration functions.
Patterns to Demonstrate:
Success Criteria:
Network Errors (Retry):
timeout - Connection/request timeoutServer Errors (Retry):
500 Internal Server Error502 Bad Gateway503 Service Unavailable504 Gateway TimeoutRate Limiting (Retry):
429 Too Many RequestsAuthentication Errors (DO NOT Retry):
401 Unauthorized403 ForbiddenClient Errors (DO NOT Retry):
400 Bad Request404 Not Found422 Unprocessable EntityExponential Backoff:
Attempt 1: Wait 1 second
Attempt 2: Wait 2 seconds
Attempt 3: Wait 4 seconds
Attempt 4: Wait 8 seconds
Best for: Most scenarios, prevents server overload
Linear Backoff:
Attempt 1: Wait 1 second
Attempt 2: Wait 2 seconds
Attempt 3: Wait 3 seconds
Attempt 4: Wait 4 seconds
Best for: Predictable retry timing
Fixed Backoff:
Attempt 1: Wait 1 second
Attempt 2: Wait 1 second
Attempt 3: Wait 1 second
Attempt 4: Wait 1 second
Best for: Testing, not recommended for production
Once you've completed all TODOs, try these advanced challenges:
Prevent "thundering herd" problem by adding randomness to retry delays.
calculateBackoffWithJitter(attempt, baseDelay) {
const exponentialDelay = baseDelay * Math.pow(2, attempt);
const jitter = Math.random() * 1000; // 0-1000ms random jitter
return exponentialDelay + jitter;
}
Why it matters: When many clients retry at the same time, they can overwhelm the server. Jitter spreads out retry attempts.
Adjust retry delays based on recent success rates.
Concept: If success rate is low (many failures), increase backoff delays. If success rate is high, use normal delays.
Implementation Hints:
(2.0 - successRate)Limit concurrent requests to prevent resource exhaustion.
Requirements:
Real-World Use: Prevents browser/server from being overwhelmed by too many simultaneous API calls.
Create a simple health check API endpoint simulator.
Features:
{ status: "healthy" } when server is good{ status: "degraded" } when errors are highError Classification (already implemented):
isRetryableError(error) {
const retryablePatterns = [
/timeout/i, /500/i, /502/i, /503/i, /504/i, /429/i
];
const nonRetryablePatterns = [
/400/i, /401/i, /403/i, /404/i, /422/i
];
// Check non-retryable first
if (nonRetryablePatterns.some(pattern => pattern.test(error.message))) {
return false;
}
return retryablePatterns.some(pattern => pattern.test(error.message));
}
Backoff Calculation (already implemented):
calculateBackoffDelay(attemptNumber) {
switch (this.backoffType) {
case 'exponential':
return this.baseDelay * Math.pow(2, attemptNumber);
case 'linear':
return this.baseDelay * (attemptNumber + 1);
case 'fixed':
return this.baseDelay;
default:
return this.baseDelay;
}
}
Your TODO: Complete the Retry Loop
async makeRequestWithRetry(errorType, requestName) {
let attempt = 0;
let lastError = null;
while (attempt <= this.maxRetries) {
try {
// TODO: Check circuit breaker
// TODO: Make the API request
// TODO: On success, reset circuit breaker and return
} catch (error) {
lastError = error;
attempt++;
// TODO: Classify error (retryable?)
// TODO: Calculate backoff delay
// TODO: Wait before retry OR throw if max retries reached
}
}
}
One. Retryable Errors:
2. Non-Retryable Errors:
3. Circuit Breaker:
4. Statistics Tracking:
Check Console Logs:
// Look for these patterns in your code
console.log('Cache hit!'); // From successful cache retrieval
console.log('Cache miss - fetching from API'); // Network request needed
Verify Error Classification:
Monitor Circuit Breaker:
activity-09-error-handling/
├── index.html # Error handling dashboard and controls
├── styles.css # Error visualization styling
├── script.js # ErrorHandler class with TODOs
├── package.json # Project metadata
└── README.md # This file
Where You'll Use These Patterns:
Production Tools:
axios-retry packageEssential Reading:
Video Tutorials:
Next Steps:
Congratulations! You've learned the most critical skill for production API development. Error handling isn't optional - it's what separates toy projects from professional applications. Keep practicing these patterns!