Challenge 2 — Solution Task: Write 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. function createCachedFetcher(ttlMs) { const cache = new Map(); return async function cachedFetch(url) { const cached = cache.get(url); if (cached && Date.now() - cached.timestamp < ttlMs) { console.log("Cache hit:", url); return cached.data; } console.log("Fetching from network:", url); const response = await fetch(url); const data = await response.json(); cache.set(url, { data, timestamp: Date.now() }); return data; }; } const fetchWithCache = createCachedFetcher(5000); async function run() { await fetchWithCache("https://jsonplaceholder.typicode.com/posts/1"); await fetchWithCache("https://jsonplaceholder.typicode.com/posts/1"); } run(); Expected output: Fetching from network: https://jsonplaceholder.typicode.com/posts/1 Cache hit: https://jsonplaceholder.typicode.com/posts/1 Notes: - The first call has nothing in cache yet, so cache.get(url) returns undefined, and the "if" check fails immediately — a real fetch happens, and the result is stored with the current timestamp. - The second call (run moments later, well within the 5000ms TTL) finds the cached entry and Date.now() - cached.timestamp is still less than 5000 — it returns the cached data instantly, with no second network request at all. - Calling fetchWithCache again after waiting more than 5 seconds would print "Fetching from network" a second time, since the cached entry would have expired by then.