Błędy limitu zapytań

Ostatnia aktualizacja: 3 miesiące temu

Jeśli widzisz 429 Too Many Requests, oznacza to, że wywołujesz API zbyt często. Oto jak obsłużyć to poprawnie.

Błąd

HTTP 429 Too Many Requests
{
  "error": "Limit exceed."
}

Dlaczego tak się dzieje

Limity zapytań chronią API przed nadmiernym użyciem:

  • Zbyt wiele żądań w krótkim czasie

  • Agresywne odpytywanie lub skrobanie (scraping)

  • Brak opóźnienia między żądaniami

  • Równoległe żądania bez ograniczania (throttling)

Strategia wykładniczego backoffu

Najlepszym sposobem obsługi limitów zapytań jest wykładniczy backoff — czekaj dłużej po każdej ponownej próbie:

async function fetchWithBackoff(url, options, maxRetries = 5) {
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    try {
      const response = await fetch(url, options);
      
      if (response.status === 429) {
        const waitTime = Math.pow(2, attempt) * 1000; // 1s, 2s, 4s, 8s, 16s
        console.log(`Rate limited. Waiting ${waitTime}ms before retry ${attempt + 1}/${maxRetries}`);
        
        await new Promise(resolve => setTimeout(resolve, waitTime));
        continue;
      }
      
      if (!response.ok) {
        throw new Error(`HTTP ${response.status}`);
      }
      
      return await response.json();
      
    } catch (error) {
      if (attempt === maxRetries - 1) throw error;
    }
  }
  
  throw new Error('Max retries exceeded');
}

Zapobieganie limitom zapytań

Dodawaj opóźnienia między żądaniami:

// Źle: Szybkie, wielokrotne żądania
for (const id of mediaIds) {
  await api.getResource(id); // Brak opóźnienia
}
// Dobrze: Ograniczone (throttled) żądania
for (const id of mediaIds) {
  await api.getResource(id);
  await sleep(500); // Opóźnienie 500 ms
}

Grupuj operacje:

// Przetwarzanie w partiach po 10 z opóźnieniami
const batchSize = 10;
for (let i = 0; i < mediaIds.length; i += batchSize) {
  const batch = mediaIds.slice(i, i + batchSize);
  await Promise.all(batch.map(id => api.getResource(id)));
  
  if (i + batchSize < mediaIds.length) {
    await sleep(2000); // 2 s między partiami
  }
}

Buforuj odpowiedzi (cache):

const cache = new Map();
async function getCachedResource(mediaId) {
  if (cache.has(mediaId)) {
    return cache.get(mediaId);
  }
  
  const data = await api.getResource(mediaId);
  cache.set(mediaId, data);
  return data;
}

Czego NIE robić

  • ❌ Ponawiać natychmiast bez opóźnienia

  • ❌ Wysyłać równoległych żądań bez limitu

  • ❌ Ignorować błędy 429

  • ❌ Stosować stałe krótkie opóźnienia (zawsze używaj wykładniczego backoffu)

Jeśli problem nadal występuje

Skontaktuj się z wsparciem dla deweloperów, jeśli w sposób uzasadniony potrzebujesz wyższych limitów zapytań dla swojego scenariusza. Podaj szczegóły dotyczące:

  • Twojej aplikacji i zastosowania

  • Oczekiwanej liczby żądań

  • Aktualnej implementacji (z backoffem)

Czy ten artykuł był pomocny?