Debouncing reduces the number of quote requests. It does not prevent an earlier request from resolving after a later one. A swap form needs both traffic control and response identity checks.
Give each request a generation
Increment a counter whenever the trade context changes. Capture the counter with the normalized chain, account, tokens, amount and recipient before starting the request. A response may update the form only if its generation still matches the active context.
Illustrative control flow
edit input → increment generation → clear executable quote
wait for input pause → request with captured generation
response → compare generation → accept or discardAbortController can cancel fetch work and response consumption. Abort the previous request when starting a replacement, but keep the generation check: cancellation can race with completion and does not undo work already performed remotely.
Separate loading from freshness
A previous estimate can remain visible while refreshing if the interface clearly marks it as stale. It must not remain executable. Store displayEstimate and executableQuote separately so a loading animation cannot accidentally preserve an old transaction button.
Do not debounce the action that clears unsafe state. Invalidation should occur immediately on input change; only the next network request waits. Likewise, a wallet account change invalidates quotes even when the token amount has not changed.
A deterministic test
Start request A for one unit, then B for ten units. Resolve B first and A second. The final output must belong to ten units. Repeat with A rejecting after B succeeds: the old failure must not replace the new successful quote with an error message. These tests need controlled promises, not a slow live endpoint.
Sources & verification (1)
Source-check date is recorded in the article details. URLs are provided for manual verification. Use Copy to keep this page open.
- AbortController
Abortable requests and response consumption
https://developer.mozilla.org/en-US/docs/Web/API/AbortController