Take a moment to think about this
By the end of Part 2, all the CRUD operations work — but if a Network error, a 401 Unauthorized, or a 429 Too Many Requests shows up, the program can still crash. In this part, we'll combine what the Errors lesson taught about parsing an error response body with what the Rate Limit lesson taught about handling a 429 status, and write it all into a single shared wrapper function called request(). Every API call will be routed through this wrapper, so all our error-handling logic lives in one place. Finally, following the Versioning lesson, we'll add the Accept-Version header too, and round out the project by documenting everything — the README.md and the full command list.
Let's build it for real
Write a helper function called request(method, path, body) and gather all the fetch, error-checking, and JSON-parsing logic inside it. When the status is 429, add exponential backoff logic that retries using the Retry-After header (or a fixed delay), up to a maximum of 3 times. For 4xx/5xx errors, pull error.message out of the response body and print it as a user-friendly message with console.error. Refactor createUser/getUsers/updateUser/deleteUser so they all call the request() wrapper, and finally, write up the command list and setup steps in README.md to round out the project.
Code Example
async function request(method, path, body, attempt = 1) {
const res = await fetch(`${API_BASE_URL}${path}`, {
method,
headers: {
Authorization: `Bearer ${API_TOKEN}`,
'Content-Type': 'application/json',
'Accept-Version': 'v1',
},
body: body ? JSON.stringify(body) : undefined,
});
if (res.status === 429 && attempt <= 3) {
const delay = attempt * 1000; // exponential-ish backoff
console.warn(`Rate limited, retrying in ${delay}ms...`);
await new Promise((r) => setTimeout(r, delay));
return request(method, path, body, attempt + 1);
}
const data = await res.json().catch(() => ({}));
if (!res.ok) {
throw new Error(data.error?.message || `Request failed: ${res.status}`);
}
return data;
}When a rate limit (429) hits, the CLI won't crash — it'll show a retry message and automatically try again, and for errors like 401/404 it'll display a readable message too.5-Minute Try-It
Within 5 minutes, deliberately set API_TOKEN to something wrong, run request(), and check whether the error message actually reads as user-friendly.
A Quick Word of Caution
If your retry logic runs too aggressively without any delay, it can actually make the rate limit worse — so stick to the backoff delay guideline from the Rate Limit lesson.