API fetch — это API JavaScript для выполнения HTTP-запросов. Это замена XMLHttpRequest, которая устарела в большинстве браузеров. Это API на основе обещаний, что означает, что он возвращает объект Promise, который разрешается или отклоняется после завершения запроса.

Давайте посмотрим на функцию fetch().

fetch(url)
  .then((response) => response.json())
  .then((data) => console.log(data))
  .catch((error) => console.error(error));

Это здорово, но иногда мы хотим отменить уже инициированный запрос.

Давайте рассмотрим следующий пример.
Предположим, у нас есть поисковый ввод, и мы хотим показать предложения по типам пользователей. когда пользователь вводит символ, мы вызываем функцию fetch() и передаем значение поля ввода поиска в качестве параметра URL.

fetch(`${url}?q=${searchInput.value}`)
  .then((response) => response.json())
  .then((data) => console.log(data))
  .catch((error) => console.error(error));

Проблема:

Функция fetch() вызывается каждый раз, когда пользователь вводит символ. Это неэффективный подход, поскольку он вызывается несколько раз, и нас интересует только последний ответ.

Решение:

Используйте функцию debounce(), чтобы ограничить количество вызовов функции fetch(). Он будет вызываться только после того, как пользователь перестанет печатать в течение определенного периода времени (100 мс). Это хорошая практика, позволяющая избежать ненужных вызовов API.

Пограничный случай: что, если пользователь начнет печатать сразу после вызова debounce(). В этом случае функция fetch() будет вызвана снова. Это лучше, чем предыдущий подход.

Как с этим справиться?

Вот здесь и пригодится AbortController. Мы можем использовать AbortController для отмены уже инициированного запроса (используя выборку). Современные браузеры имеют встроенный интерфейс AbortController.

Вы можете создать новый объект AbortController, используя конструктор AbortController().

Характеристики:

AbortController.signal:

Возвращает экземпляр объекта AbortSignal, который можно использовать для связи или прерывания запроса DOM.

Метод:

AbortController.abort():

Прерывает запрос DOM до его завершения. Когда мы прерываем асинхронную операцию, обещание отклоняется с DOMException с именем AbortError.

Реальный пример

Я не буду создавать здесь функцию debounce(), но давайте рассмотрим следующий пример.

<!DOCTYPE html>
<html>
  <body>
    <input id="search" type="number" />
    <script>
      const results = [];
      const search = document.getElementById("search");
      let controller = new AbortController();
      let signal = controller.signal;
      const getPost = async (value, signal) => {
        try {
          const response = await fetch(
            `https://jsonplaceholder.typicode.com/posts/${value}`,
            { signal }
          );
          results.push(`Success: ${value}`);
        } catch (error) {
          if (error.name === "AbortError") {
            results.push("API failure");
          } else {
            console.log("Some other error");
          }
        } finally {
          console.log("Status", results);
        }
      };
      const onChange = () => {
        const value = search.value;
        if (value) {
          controller.abort();
          controller = new AbortController();
          signal = controller.signal;
          getPost(value, signal);
        }
      };
      search.onkeyup = onChange;
    </script>
  </body>
</html>

Реагировать пример

useEffect(() => {
  const controller = new AbortController();
  const signal = controller.signal;
  const results = [];
  const getPost = async (value) => {
    try {
      const response = await fetch(
        `https://jsonplaceholder.typicode.com/posts/${value}`,
        { signal }
      );
      results.push(`Success: ${value}`);
    } catch (error) {
      if (error.name === "AbortError") {
        results.push("API failure");
      }
    } finally {
      console.log("Status", results);
    }
  };
  getPost(1);
  return () => {
    // Cancel the request on unmount
    controller.abort();
  };
}, []);

Примечание. Лучшим подходом может быть сочетание debounce() и AbortController.

Обязательно прочитайте, если вы еще не читали

Реагирование на передовые методы и шаблоны для сокращения кода — Часть 1
Реагирование на передовые практики и шаблоны для сокращения кода — Часть 2
28 методов массива Javascript: памятка для разработчика

Больше контента на Средних

Следуйте за мной на Github, Twitter, LinkedIn, Dev.to и Stackblitz.