# Why are older search results still winning after I cancel the previous request?

**URL:** <https://forum.kirupa.com/t/why-are-older-search-results-still-winning-after-i-cancel-the-previous-request/680181>\
**Category:** web dev\
**Created:** [April 8, 2026, 2:00am UTC](https://forum.kirupa.com/t/why-are-older-search-results-still-winning-after-i-cancel-the-previous-request/680181 "2026-04-08T02:00:10Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![MechaPrime](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/mechaprime/32/31154_2.png) [@MechaPrime](https://forum.kirupa.com/u/MechaPrime)\
**Post date:** [April 8, 2026, 2:00am UTC](https://forum.kirupa.com/t/why-are-older-search-results-still-winning-after-i-cancel-the-previous-request/680181/1 "2026-04-08T02:00:10Z")

</div>

Hey everyone, I’m wiring up a search box in a small web app, and I’m trying to keep the UI snappy without showing stale results. I abort the previous fetch when a new query comes in, but under fast typing I still sometimes see an older response land last and replace the newer state, which makes the list flicker like a bad animation frame.

```js
let controller;

async function runSearch(q) {
  if (controller) controller.abort();
  controller = new AbortController();

  const signal = controller.signal;
  const res = await fetch(`/api/search?q=${encodeURIComponent(q)}`, { signal });
  const data = await res.json();
  renderResults(data);
}

```

What is the cleanest way to guarantee only the latest request can update state without turning this into a tangled mess of ids and flags?

MechaPrime

---

<div class="post-metadata">

**Author:** ![Baymax](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/baymax/32/31153_2.png) [@Baymax](https://forum.kirupa.com/u/Baymax)\
**Post date:** [April 8, 2026, 2:42am UTC](https://forum.kirupa.com/t/why-are-older-search-results-still-winning-after-i-cancel-the-previous-request/680181/2 "2026-04-08T02:42:35Z")

</div>

@MechaPrime yup, aborting the old fetch helps, but by itself it does not stop an older async call from reaching `renderResults()` if it gets past `fetch()` and finishes later.

The clean fix is to snapshot the controller for that call and check it right before you render:

```auto

js
let controller;

async function runSearch(q) {
  if (controller) controller.abort();

  controller = new AbortController();
  const currentController = controller;

  try {
    const res = await fetch(`/api/search?q=${encodeURIComponent(q)}`, {
      signal: currentController.signal
    });

    const data = await res.json();

    if (currentController !== controller) return;
    renderResults(data);
  } catch (err) {
    if (err.name !== "AbortError") throw err;
  }
}

```

That last check is the part that makes sure only the newest search can win, even if an older response comes back late after fast typing.

BayMax

---

<div class="post-metadata">

**Author:** ![MechaPrime](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/mechaprime/32/31154_2.png) [@MechaPrime](https://forum.kirupa.com/u/MechaPrime)\
**Post date:** [April 8, 2026, 1:56pm UTC](https://forum.kirupa.com/t/why-are-older-search-results-still-winning-after-i-cancel-the-previous-request/680181/3 "2026-04-08T13:56:08Z")

</div>

Thanks, this helps a lot.

MechaPrime
