Working with APIs
Fundamentals Chapter 10 covered a single fetch call in isolation. Real APIs rarely hand back everything in one response — they paginate, they rate-limit, and repeatedly re-fetching the same unchanged data wastes both time and the API's generosity. This final chapter brings together fetch, generators (Chapter 2), debounce (Chapter 4), and closures into the patterns that show up constantly in production code.
Pagination — Fetching Data in Pages
Most APIs return data in pages to limit response size — each call needs a page number, and a flag (here, hasMore) signals whether further pages exist. while (hasMore) keeps requesting and merging pages (using spread, Intermediate Chapter 1) until the API says there's nothing left.
A Generator Wrapping Pagination
async function* combines Chapter 2's generators with async/await — each yield hands back one page as soon as it's fetched, rather than waiting for every page to load before returning anything. for await (... of ...) is for...of's counterpart for these async generators, awaiting each yielded value automatically.
Rate Limiting — Respecting an API's Request Caps
Many APIs reject requests beyond a certain rate (e.g. "max 2 requests/second"). This rate limiter — using Chapter 4's module pattern, a queue, and a spaced-out setTimeout delay between each item — ensures requests are spread out automatically, regardless of how quickly the calling code tries to fire them off.
429 Too Many Requests is the standard signal an API sends when its rate limit is exceeded. Production code should check for it specifically (response.status === 429) and back off — retrying immediately just gets rejected again, and repeatedly hitting it can lead to a temporary or permanent IP ban from the API provider.
Caching — Avoiding Repeated, Unnecessary Requests
Another module-pattern closure, this time holding a Map (a key/value structure similar to Go's map from the Go course, distinct from a plain object) keyed by URL. ttlMs ("time to live") decides how long a cached response stays valid — repeated calls within that window return instantly from memory, with no network request at all.
| Concern | Tool/Pattern |
|---|---|
| Fetching multiple pages | while loop checking a hasMore flag |
| Streaming pages one at a time | async function* + for await...of |
| Respecting a rate limit | A queue + spaced setTimeout delays between requests |
| Avoiding duplicate requests | A Map cache with a time-to-live check |
Coding Challenges
Write an async function fetchAllUsers() using the while-loop pagination pattern from this chapter, against https://jsonplaceholder.typicode.com/users (this particular API returns all results in one page, so simulate hasMore by stopping once the returned array's length is 0 on a fake "page 2"). Log the total count fetched.
📄 View solutionWrite the createCachedFetcher function from this chapter exactly as shown. Create fetchWithCache with a 5000ms TTL, call it twice in a row with the same URL (https://jsonplaceholder.typicode.com/posts/1), and log a message indicating whether each call hit the cache or made a real network request.
📄 View solutionWrite a function that checks a fetch Response object's status and, if it's 429, logs "Rate limited — backing off" and waits 2 seconds (using a Promise + setTimeout) before returning a retry signal; otherwise it returns the response's parsed JSON normally. Test it with a mocked response object of { status: 429 }.
📄 View solutionChapter 5 Quick Reference
- Pagination: loop while a hasMore-style flag is true, merging each page's results
- async function* + for await...of — stream paginated results one page at a time
- 429 Too Many Requests — the standard "you've hit the rate limit" HTTP status
- Rate limiting: a queue + spaced delays, ensuring requests never exceed an allowed rate
- Caching: a Map keyed by URL, with a timestamp + TTL check before reusing a cached value
- All of these patterns combine closures, fetch, generators, and timers — no new core syntax
- This completes JavaScript Advanced and the JavaScript course overall as currently planned across all 3 courses.