A type-ahead fires a request per keystroke and the responses arrive out of order, so the results for a shorter query can overwrite the results for a longer one.
let controller;
async function search(term) {
controller?.abort();
controller = new AbortController();
try {
const res = await fetch(`/search?q=${encodeURIComponent(term)}`,
{ signal: controller.signal });
render(await res.json());
} catch (e) {
if (e.name !== 'AbortError') throw e;
}
}
Distinguishing the abort error from a real failure is required, or every cancellation is reported as a bug. The signal can be passed to several fetches to cancel them together, which is the neat part. It does not stop the server doing the work — the request has been sent — so this is about the client’s state rather than about saving anyone’s resources.