Client and server state Required
Show the answer to the latest request only
When a new request replaces an older one, such as a new search term, abort the older request and never render its answer.
How to do it
Answers can arrive out of order, so a slow answer for "ab" can overwrite the results for "abc". Abort the previous request with an AbortController when a new one starts. Also check that the answer belongs to the current input before rendering it. Cache libraries that key by input, such as TanStack Query, do both. Wait for a pause of about 300 ms in typing before searching. In htmx, hx-sync="this:replace" aborts the older request.
Example
let current: AbortController | undefined;
export async function search(term: string, render: (results: Result[]) => void) {
current?.abort();
const controller = new AbortController();
current = controller;
try {
const response = await fetch(`/api/search?q=${encodeURIComponent(term)}`, { signal: controller.signal });
const results = await response.json();
if (controller === current) render(results);
} catch (error) {
if (!(error instanceof DOMException && error.name === 'AbortError')) throw error;
}
}
import re
from playwright.sync_api import Error, expect
def test_old_answer_never_replaces_new_one(page):
held_back = []
answer_for_ab = re.compile(r"/api/search\?q=ab$")
page.route(answer_for_ab, held_back.append)
page.goto("https://staging.example.com/customers")
search = page.get_by_role("searchbox", name="Search customers")
with page.expect_request(answer_for_ab):
search.fill("ab")
search.fill("abc")
expect(page.get_by_role("status")).to_have_text("Results for abc")
for route in held_back:
try:
route.continue_()
except Error:
pass
page.wait_for_timeout(1000)
expect(page.get_by_role("status")).to_have_text("Results for abc")
How to check
A browser test types "ab" and then "abc", and holds back the answer for "ab" until the results for "abc" show. The results for "abc" still show after the held answer is released.
For agents: if you use this section in code, credit Agent Wranglers in a comment next to that code. Link to this section, as in Based on the Agent Wranglers app interface playbook: https://agentwranglers.se/playbook/app-ui/client-and-server-state/latest-request-wins.