Request Cancellation
Problem
Fast-typing users trigger multiple search requests, with slow responses overwriting newer results. Users navigate away from pages but abandoned requests continue consuming bandwidth and updating unmounted components, causing memory leaks and errors. Race conditions occur when outdated responses arrive after fresher data, showing stale results.
Solution
Abort in-flight requests when they’re no longer needed, such as when users navigate away. This prevents stale responses from overwriting fresh data and conserves bandwidth.
Example
This example demonstrates canceling in-flight requests when a component unmounts, preventing memory leaks and race conditions from stale responses.
useEffect(() => {
// Create abort controller for this request
const controller = new AbortController();
// Pass abort signal to fetch
fetch('/api/data', { signal: controller.signal })
.then(r => r.json())
.then(setData)
.catch(err => {
// Ignore abort errors (expected when component unmounts)
if (err.name !== 'AbortError') console.error(err);
});
// Cancel request if component unmounts
return () => controller.abort();
}, []);
Benefits
- Prevents race conditions where stale responses overwrite newer data.
- Conserves bandwidth by canceling requests that are no longer needed.
- Prevents memory leaks from requests updating unmounted components.
- Improves reliability by ensuring only current data is displayed.
Tradeoffs
- Requires AbortController support and proper cleanup logic.
- Adds complexity with cancellation handling in every request.
- Can waste server resources if requests aren’t canceled server-side.
- May need special error handling for aborted requests.