Skip to main content
← ⚑ JavaScript & the browserΒ·Module C7 Β· Lesson 10
TaskDefine HttpError extends Error (with .status field) and NotFoundError extends HttpError. Write async fetchJson(url) that throws NotFoundError on status 404 and HttpError on any other not-ok. For each id in [1, 999], try fetchJson('/api/users/' + id) β€” success path logs user.name; instanceof NotFoundError β†’ log 'not found'.

Capstone: typed-error fetch wrapper

250 XP14 min
Theory

The shape every real codebase needs

A fetch wrapper that turns HTTP statuses into typed errors. Every call site gets clean narrowing: 404 β†’ null, anything else not-OK β†’ throw.

class HttpError extends Error {
  constructor(status, statusText) {
    super(\`HTTP ${status} ${statusText}\`);
    this.name = "HttpError";
    this.status = status;
  }
}
class NotFoundError extends HttpError {
  constructor(s, t) { super(s, t); this.name = "NotFoundError"; }
}

async function fetchJson(url) {
  const r = await fetch(url);
  if (r.status === 404) throw new NotFoundError(r.status, r.statusText);
  if (!r.ok)            throw new HttpError(r.status, r.statusText);
  return r.json();
}

Calling it

try {
  const user = await fetchJson("/api/users/1");
  console.log(user.name);
} catch (err) {
  if (err instanceof NotFoundError) return null;
  throw err;  // unknown β€” let it bubble
}

Why this scales

The pattern extends trivially: class RateLimitError, class BadRequestError, class UnauthorizedError β€” same five-line shape, each catches its own status. Every API client in your codebase reads the same way.

πŸ”’

Sign up to start coding

Theory is open to everyone. The interactive editor, live preview, and check are unlocked with a 7-day free trial β€” card required, cancel anytime.

Sign up β€” free trial β†’

First 10 lessons in each track are free. No card needed for those.

← PreviousNext lesson β†’

Get one Python or web tip a day β€” by email

Short, hand-written, no spam. Unsubscribe in one click.