How do you debounce async field validation without showing stale errors?

Hey everyone, I’m wiring up a signup form and I’m trying to do async username checks without the UI flickering or showing the wrong message when requests finish out of order.

const input = document.querySelector('#username');
const status = document.querySelector('#status');
let t;
let lastReq = 0;

async function checkName(name) {
  const res = await fetch(`/api/username?u=${encodeURIComponent(name)}`);
  return res.json(); // { ok: boolean, reason?: string }
}

input.addEventListener('input', () => {
  clearTimeout(t);
  const name = input.value.trim();
  t = setTimeout(async () => {
    const reqId = ++lastReq;
    status.textContent = 'Checking…';
    const result = await checkName(name);
    if (reqId !== lastReq) return; // ignore stale
    status.textContent = result.ok ? 'Available' : (result.reason || 'Taken');
  }, 250);
});

What’s the cleanest pattern here to avoid stale responses and also not leak work (AbortController, request id, something else) when validation is happening constantly while the user types?

1 Like