← Recipes

阅读中文版本

Deduplicate Concurrent Client Requests

Share one in-flight promise among callers of the same resource so a burst of identical requests hits the network once.

~30 minfrontendperformancehttp

Task

Stop a UI that triggers the same fetch from many components from issuing duplicate network calls.

When to use this

Several components mount at once, each calls the same endpoint, and the app sends many identical requests that all resolve with the same data.

Prerequisites

  • A promise-based HTTP client
  • A key derived from the request

Steps

1. Key each request by method and URL plus relevant headers.

Expected output: Identical requests share a key.

2. Keep a map of in-flight promises and return the existing one when present.

Expected output: Concurrent callers await a single network call.

3. Remove the entry in a finally block so later callers can refetch.

Expected output: Deduplication does not cache forever.

4. Distinguish this from caching: dedup only merges concurrent, not sequential, calls.

curl -s https://api.example.com/user/me -o /dev/null -w "%{http_code}"

Expected output: The behavior is predictable.

Troubleshooting

Problem

Stale shared result

Solution

Remove the promise on settle; do not keep it as a permanent cache.

Problem

Different auth tokens share a key

Solution

Include the authorization scope in the key so cross-user requests never merge.

Limitations

  • Deduplication only helps concurrent requests; it does nothing for sequential repeats.
  • It must not merge requests with different bodies for non-idempotent methods.

Context

Stop a UI that triggers the same fetch from many components from issuing duplicate network calls. Several components mount at once, each calls the same endpoint, and the app sends many identical requests that all resolve with the same data.

Steps

  1. Key each request by method and URL plus relevant headers. Expected: Identical requests share a key.
  2. Keep a map of in-flight promises and return the existing one when present. Expected: Concurrent callers await a single network call.
  3. Remove the entry in a finally block so later callers can refetch. Expected: Deduplication does not cache forever.
  4. Distinguish this from caching: dedup only merges concurrent, not sequential, calls. Expected: The behavior is predictable.
const inflight = new Map();
function get(url) {
  const key = `GET ${url}`;
  if (!inflight.has(key)) {
    inflight.set(key, fetch(url).finally(() => inflight.delete(key)));
  }
  return inflight.get(key);
}

Verify

  • Identical requests share a key.
  • Concurrent callers await a single network call.
  • Deduplication does not cache forever.
  • The behavior is predictable.

Limits

  • Deduplication only helps concurrent requests; it does nothing for sequential repeats.
  • It must not merge requests with different bodies for non-idempotent methods.