Przeglądaj źródła

⚡ feat: implement GET request deduplication in API layer

Add request deduplication mechanism to prevent duplicate GET requests
to the same endpoint within the same timeframe, significantly reducing
unnecessary network overhead.

**Changes:**
- Add `patchAPIInstance()` function to intercept and deduplicate GET requests
- Implement in-flight request tracking using Map with URL+params as unique keys
- Apply deduplication patch to both initial API instance and `updateAPI()` recreated instances
- Add `disableDuplicate: true` config option to bypass deduplication when needed

**Benefits:**
- Eliminates redundant API calls caused by component re-renders or rapid user interactions
- Reduces server load and improves application performance
- Provides automatic protection against accidental duplicate requests
- Maintains backward compatibility with existing code

**Technical Details:**
- Uses Promise sharing for identical concurrent requests
- Automatically cleans up completed requests from tracking map
- Preserves original axios functionality with minimal overhead
- Zero breaking changes to existing API usage

Addresses the issue observed in EditChannel.js where multiple calls
were made to the same endpoints during component lifecycle.
Apple\Apple 11 miesięcy temu
rodzic
commit
3f67db1028
1 zmienionych plików z 32 dodań i 0 usunięć
  1. 32 0
      web/src/helpers/api.js

+ 32 - 0
web/src/helpers/api.js

@@ -12,6 +12,36 @@ export let API = axios.create({
   },
 });
 
+function patchAPIInstance(instance) {
+  const originalGet = instance.get.bind(instance);
+  const inFlightGetRequests = new Map();
+
+  const genKey = (url, config = {}) => {
+    const params = config.params ? JSON.stringify(config.params) : '{}';
+    return `${url}?${params}`;
+  };
+
+  instance.get = (url, config = {}) => {
+    if (config?.disableDuplicate) {
+      return originalGet(url, config);
+    }
+
+    const key = genKey(url, config);
+    if (inFlightGetRequests.has(key)) {
+      return inFlightGetRequests.get(key);
+    }
+
+    const reqPromise = originalGet(url, config).finally(() => {
+      inFlightGetRequests.delete(key);
+    });
+
+    inFlightGetRequests.set(key, reqPromise);
+    return reqPromise;
+  };
+}
+
+patchAPIInstance(API);
+
 export function updateAPI() {
   API = axios.create({
     baseURL: import.meta.env.VITE_REACT_APP_SERVER_URL
@@ -22,6 +52,8 @@ export function updateAPI() {
       'Cache-Control': 'no-store',
     },
   });
+
+  patchAPIInstance(API);
 }
 
 API.interceptors.response.use(