Question presented to candidate:
"Several components on our dashboard load the same user, and each one fires its own request. Build a small useQuery-style data-fetching helper: components that ask for the same key should share one cached result and one in-flight request, and a failed request should retry a few times with backoff before showing an error. No libraries; a fake fetcher is fine."
Requirements:
useQuery(key, fetcher)(a hook in React, a composable in Vue, a service-backed helper in Angular) returnsstatus,data,error,isFetchingandfailureCount.- Caching: a key fetched less than
staleTimeago is served from cache with no new call. - Deduplication: concurrent callers of the same key share one promise, so the fetcher runs once.
- Retry: on failure, retry up to
retrytimes with exponential backoff (retryDelay * 2^attempt), then show the error. invalidate(key)marks a key stale and refetches it for every mounted reader, keeping the old data on screen while it loads.
What a strong answer should cover:
- The cache must live outside any one component (module scope or an app-wide service), keyed by a stable string.
- Storing the in-flight promise in the cache entry is what makes dedupe work, and clearing it in
finallyis what lets the next fetch happen. - A subscription model so every reader re-renders when the entry changes:
useSyncExternalStorein React, ashallowRefin Vue, asignalin Angular. - Retry with exponential backoff, a capped number of attempts, and keeping the error in state rather than throwing into the UI.
- Stale-while-revalidate: show cached data while a background refetch runs.
- Proof by counting calls to a fake fetcher, including React StrictMode running effects twice.
Clarifying questions expected:
- "How fresh does the data need to be: is a few seconds of stale data acceptable?"
- "Which errors should be retried? A 404 probably should not be, a 503 should."
- "Do we need cancellation or garbage collection of unused cache entries for this round?"
Code / implementation expected: Yes. A working cache module plus the hook/composable/service, and a demo that shows the call counts.