Как мне справиться с ошибками 429 от eleventy-fetch?

Вопрос или проблема

Я делаю запрос с помощью eleventy-fetch следующим образом:

let response = await EleventyFetch(url, {
    duration: "1h",
    type: "json"
  });

Однако иногда он завершается с ошибкой:

Плохой ответ для [url] (429): Слишком много запросов (через ошибку)

Я знаю, что запрашиваю слишком часто, поэтому хочу реализовать экспоненциальное ожидание. Однако моя первая попытка не сработала:

let response;
let attempts = 0;
const maxAttempts = 5;

while (attempts < maxAttempts) {
  try {
    response = await EleventyFetch(url, {
      duration: "1h",
      type: "json"
    });
    break; // Если запрос успешен, выход из цикла
  } catch (err) {
    if (err.response && err.response.status === 429) {
      attempts++;
      const waitTime = Math.pow(2, attempts) * 1000; // Экспоненциальное ожидание
      console.warn(`Лимит частоты превышен. Повторный запрос через ${waitTime / 1000} секунд...`);
      await new Promise(resolve => setTimeout(resolve, waitTime));
    } else {
      throw err; // Если это не ошибка 429, выбросить ошибку снова
    }
  }
}

Ошибка продолжает возникать, и экспоненциальное ожидание не происходит. Что я сделал не так?

Вам следует искать err.cause, а не err.response.

Исходный код RemoteAssetCache.js для eleventy-fetch показывает, где возникает ошибка:

if (!response.ok) {
    throw new Error(
        `Плохой ответ для ${this.displayUrl} (${response.status}): ${response.statusText}`,
        { cause: response },
    );
}

Здесь ответ прикреплён к ошибке как свойство cause.

Чтобы сделать ваше экспоненциальное ожидание работающим, вам просто нужно заменить err.response на err.cause:

let response;
let attempts = 0;
const maxAttempts = 5;

while (attempts < maxAttempts) {
  try {
    response = await EleventyFetch(url, {
      duration: "1h",
      type: "json"
    });
    break; // Если запрос успешен, выход из цикла
  } catch (err) {
    if (err.cause && err.cause.status === 429) {
      attempts++;
      const waitTime = Math.pow(2, attempts) * 1000; // Экспоненциальное ожидание
      console.warn(`Лимит частоты превышен. Повторный запрос через ${waitTime / 1000} секунд...`);
      await new Promise(resolve => setTimeout(resolve, waitTime));
    } else {
      throw err; // Если это не ошибка 429, выбросить ошибку снова
    }
  }
}

Ответ или решение

Чтобы корректно обрабатывать ошибки 429 (Too Many Requests) при использовании библиотеки eleventy-fetch, вам необходимо внести небольшие изменения в ваш код для реализации механизма экспоненциального отката (exponential backoff). Проблема заключается в том, что вы ищете err.response, когда на самом деле нужная информация находится в err.cause.

Вот корректный пример кода с обработкой ошибок 429:

let response;
let attempts = 0;
const maxAttempts = 5;

while (attempts < maxAttempts) {
  try {
    response = await EleventyFetch(url, {
      duration: "1h",
      type: "json"
    });
    break; // Если запрос успешен, выходим из цикла
  } catch (err) {
    // Теперь проверяем err.cause, а не err.response
    if (err.cause && err.cause.status === 429) {
      attempts++;
      const waitTime = Math.pow(2, attempts) * 1000; // Экспоненциальный откат
      console.warn(`Лимит частоты превышен. Повторная попытка через ${waitTime / 1000} секунд...`);
      await new Promise(resolve => setTimeout(resolve, waitTime));
    } else {
      throw err; // Если это не ошибка 429, повторно выбрасываем ошибку
    }
  }
}

Объяснение изменений:

  1. Использование err.cause: Вместо проверки err.response, вам нужно использовать err.cause, поскольку именно туда библиотека eleventy-fetch помещает объект ответа, в котором содержится статус ошибки.

  2. Логика повторных попыток: Если возникает ошибка 429, увеличивается количество попыток, рассчитывается время ожидания с помощью экспоненциального отката, и происходит пауза перед следующей попыткой.

  3. Проверка на другие ошибки: Если ошибка не является 429, она повторно выбрасывается, что позволяет обработать её в другом месте вашего приложения.

С помощью этих изменений, вы сможете эффективно обрабатывать ошибки 429 и минимизировать вероятность получения этих ошибок, что сделает ваши запросы к API более устойчивыми.

Оцените материал
Добавить комментарий

Капча загружается...