Code of the Day
IntermediateThe runtime

Lab: the runtime capstone

Combine async/await, closures, classes, error handling, and fetch in one connected session.

Lab · optionalJavaScript / TSIntermediate22 min
Recommended first
By the end of this lesson you will be able to:
  • Write and chain async functions using async/await
  • Use closures to create private state
  • Handle fetch errors with try/catch and status checks
  • Design a class with encapsulated state

Optional capstone lab. This session brings together the runtime module: the event loop, promises, closures, classes, error handling, and fetch. Three checkpoints that build on each other.

Warm-up — the event loop in one glance

Run this and predict the output before you see it. The order is the whole lesson:

JavaScript — editable, runs in your browser

Sync runs first, then microtasks (Promise callbacks), then the task queue (setTimeout). That ordering governs every async pattern you write.

Checkpoint 1 — counter closure

Write makeCounter(start) that returns an object with increment(), decrement(), and value() methods. The internal count starts at start and is completely private — no external code should be able to set it directly.

Counter closureJavaScript

Write makeCounter(start) returning an object with increment(), decrement(), and value() methods. The count is private — only accessible through the methods.

const c = makeCounter(5); c.increment(); c.value()6

Checkpoint 2 — async retry

Write withRetry(fn, times) that calls the async function fn up to times attempts, returning the first successful result. If all attempts throw, re-throw the last error.

Async retry wrapperJavaScript

Write async function withRetry(fn, times) that calls the async function fn up to times attempts. Return the first resolved value. If every attempt throws, re-throw the last error.

withRetry(unstableFetch, 3)resolved value on first success, or throws after 3 failures

Checkpoint 3 — graceful fetch

Run this fetch that deliberately targets a non-existent endpoint. Then modify it so that: (a) network errors are caught and logged, and (b) non-2xx HTTP responses throw a readable error with the status code.

JavaScript — editable, runs in your browser

The pattern: always check res.ok before calling .json(). A 404 or 500 is a successful HTTP exchange — fetch only rejects on network failure, not bad status codes.

Done?

Three green checks means you own the JavaScript runtime: closures for private state, async/await for sequencing, and defensive fetch for production network calls. These three patterns appear in nearly every real JS codebase.

Finished reading? Mark it complete to track your progress.

On this page