Stale Browser Responses

Browser requests can finish in a different order from the one in which the user initiated them.

Why This Matters

Search-as-you-type, filters, route transitions, and dependent selects can show stale data when an older slow response overwrites a newer result.

Working Model

Browser requests can finish in a different order from the one in which the user initiated them. Correctness comes from preserving an explicit invariant across every permitted ordering, not from expecting one observed timing.

Latest-Response Guard

let latestSearch = 0;
let activeController = null;

async function searchProducts(query) {
  const requestNumber = ++latestSearch;

  activeController?.abort();
  activeController = new AbortController();

  try {
    const response = await fetch("/api/products?q=" + encodeURIComponent(query), {
      signal: activeController.signal,
    });
    const result = await response.json();

    if (requestNumber === latestSearch) {
      renderProducts(result.data);
    }
  } catch (error) {
    if (error.name !== "AbortError") {
      showSearchError();
    }
  }
}

Cancellation reduces obsolete work. The sequence check remains important because cancellation and completion can race.

Practical Rules

  • Track a monotonically increasing request sequence.
  • Abort obsolete fetches with AbortController where appropriate.
  • Check component or page lifetime before rendering.
  • Bind responses to the inputs that produced them.
  • Treat abort as expected control flow.

Failure Modes

  • Assuming network completion order matches start order.
  • Disabling only the button while programmatic requests still overlap.
  • Rendering after navigation destroyed the owning view.
  • Using debounce as the only correctness control.

Verification

  • Simulate slow older responses.
  • Test rapid input and navigation.
  • Assert only the latest sequence renders.
  • Inspect aborted and completed requests.

What You Should Be Able To Do

After this lesson, you should be able to explain stale-response races and browser-side cancellation or latest-response guards, choose a suitable approach for a real PHP project, and verify the result instead of relying on assumptions.

Practice

Practice: Handle A Route Change

A response returns after the user leaves the page. Prevent stale rendering.

Your answer must:

  • state the intended outcome;
  • show the commands, data flow, or implementation shape;
  • identify at least one unsafe alternative;
  • explain how the result will be verified.
Show solution

Abort on teardown and also check that the route/view identity still matches before mutating state. Cancellation alone may race with completion.

The important part is not memorising one command or vendor screen. The solution makes the invariant, failure behavior, and verification evidence explicit.

Practice: Test Out-Of-Order Results

Write a deterministic browser-test scenario.

Your answer must:

  • state the intended outcome;
  • show the commands, data flow, or implementation shape;
  • identify at least one unsafe alternative;
  • explain how the result will be verified.
Show solution

Stub two requests, resolve the newer one first and the older one last, then assert the UI still shows the newer query and no stale loading state.

The important part is not memorising one command or vendor screen. The solution makes the invariant, failure behavior, and verification evidence explicit.