You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular HttpClient重复发送请求至后端并缓存旧请求问题咨询

Hey there! Let's walk through the most common reasons your code might be firing duplicate requests and hanging onto old cached data, plus easy fixes to try out:

1. Component Re-mounting or Misconfigured Effects (Framework Scenarios)

If you're using a frontend framework like React or Vue, duplicate requests often come from components re-mounting unexpectedly or effect hooks with incorrect dependencies. For example:

// ❌ Bad: Empty dependency array, but if the component re-mounts (e.g., bad key in a list), it runs again
useEffect(() => {
  fetchUserData();
}, []);

Fix: Ensure your components have unique keys when rendered in lists, and add cleanup logic to cancel in-flight requests using AbortController:

useEffect(() => {
  const controller = new AbortController();
  fetchUserData(controller.signal);

  // Cancel the request if the component unmounts or dependencies change
  return () => controller.abort();
}, [userId]); // Only trigger when userId changes
2. Duplicate Event Listeners

If you're binding request triggers (like a fetch call) to events without cleaning up old listeners, each interaction can stack up requests. For example:

// ❌ Bad: Adds a new click listener every time this code runs
document.getElementById('fetch-btn').addEventListener('click', () => fetchData());

Fix: Bind listeners only once, or remove old listeners before adding new ones. For one-time bindings, use once: true:

document.getElementById('fetch-btn').addEventListener('click', () => fetchData(), { once: true });
3. Flawed Caching Logic

Old cached data usually means your cache isn't keyed correctly or lacks expiration. If you're using a generic cache key regardless of request parameters, you'll get stale data even when the request changes:

// ❌ Bad: Same cache key for every request, so old data sticks around
const cache = {};
async function fetchUser(id) {
  if (cache['user']) return cache['user'];
  const res = await fetch(`/api/users/${id}`);
  cache['user'] = res.json();
  return cache['user'];
}

Fix: Use request-specific cache keys and add an expiration window:

const cache = {};
async function fetchUser(id) {
  const cacheKey = `user_${id}`;
  const cachedEntry = cache[cacheKey];
  
  // Return fresh cache if it's less than 5 minutes old
  if (cachedEntry && Date.now() - cachedEntry.timestamp < 300000) {
    return cachedEntry.data;
  }

  const res = await fetch(`/api/users/${id}`);
  const data = await res.json();
  cache[cacheKey] = { data, timestamp: Date.now() };
  return data;
}
4. Uncancelled Parallel Requests

If users trigger requests quickly (e.g., double-clicking a button), multiple in-flight requests can resolve out of order, showing old data even after a newer request finishes.
Fix: Add debouncing to limit how often requests fire, or cancel previous requests with AbortController:

// Debounce example: Wait 300ms after the last user action before firing the request
let debounceTimeout;
function debouncedFetchUser(id) {
  clearTimeout(debounceTimeout);
  debounceTimeout = setTimeout(() => {
    fetchUser(id);
  }, 300);
}
5. Uncontrolled Global State Triggers

If you're using global state management (Redux, Pinia, etc.), multiple components might trigger the same request action simultaneously. Without a guard, this leads to duplicates.
Fix: Add a "loading" flag to block duplicate requests while one is in flight:

let isFetching = false;
async function fetchUserAction(id) {
  if (isFetching) return; // Exit if a request is already running
  isFetching = true;

  try {
    const res = await fetch(`/api/users/${id}`);
    const data = await res.json();
    // Update global state with data
  } finally {
    isFetching = false; // Reset flag even if the request fails
  }
}

内容的提问来源于stack exchange,提问作者Egbert

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 10:31:49