← Recipes

阅读中文版本

Implement a Debounced Autocomplete

Debounce keystrokes, cancel stale requests, and render suggestions in order so the list always reflects the latest query without flooding the API.

~35 minfrontendperformanceapi-design

Task

Build an autocomplete input that queries the server after typing pauses and ignores superseded responses.

When to use this

Typing fires one request per character, responses arrive out of order, and the dropdown shows suggestions for a query the user already changed.

Prerequisites

  • An endpoint that returns suggestions for a query
  • AbortController or a request library that supports cancellation

Steps

1. Debounce the input by a short delay before issuing a request.

Expected output: Requests fire only after typing pauses.

2. Abort the previous in-flight request when a new one starts.

curl "https://api.example.com/search?q=typescr"

Expected output: Only one suggestion request is active at a time.

3. Tag each request with a sequence number and ignore responses older than the latest.

Expected output: Out-of-order responses never render stale results.

4. Render a loading state, an empty state, and clamp suggestion count.

Expected output: The dropdown never shows an empty flicker or overloads the DOM.

Troubleshooting

Problem

Abort errors surface as failures

Solution

Distinguish AbortError from real errors and ignore the former silently.

Problem

Debounce on every keystroke still slow

Solution

Combine debounce with a minimum query length and cancel-on-empty.

Limitations

  • Debounce adds latency; for very fast servers a shorter delay or throttling may feel better.
  • Server-side ranking quality matters more than client timing and cannot be fixed by debouncing.

Context

Build an autocomplete input that queries the server after typing pauses and ignores superseded responses. Typing fires one request per character, responses arrive out of order, and the dropdown shows suggestions for a query the user already changed.

Steps

  1. Debounce the input by a short delay before issuing a request. Expected: Requests fire only after typing pauses.
  2. Abort the previous in-flight request when a new one starts. Expected: Only one suggestion request is active at a time.
  3. Tag each request with a sequence number and ignore responses older than the latest. Expected: Out-of-order responses never render stale results.
  4. Render a loading state, an empty state, and clamp suggestion count. Expected: The dropdown never shows an empty flicker or overloads the DOM.
let seq = 0;
async function search(q) {
  const my = ++seq;
  const data = await (await fetch(`/api/search?q=${encodeURIComponent(q)}`)).json();
  if (my === seq) render(data);
}

Verify

  • Requests fire only after typing pauses.
  • Only one suggestion request is active at a time.
  • Out-of-order responses never render stale results.
  • The dropdown never shows an empty flicker or overloads the DOM.

Limits

  • Debounce adds latency; for very fast servers a shorter delay or throttling may feel better.
  • Server-side ranking quality matters more than client timing and cannot be fixed by debouncing.