Учебное пособие по API JavaScript Fetch: GET, POST, обработка ошибок и тайм-ауты

  1. Главная
  2. Блог
  3. Разработка программного обеспечения

Разработка программного обеспечения

Учебное пособие по API JavaScript Fetch: GET, POST, обработка ошибок и таймауты

Fetch — это встроенный способ вызова API из JavaScript, но у него есть один сюрприз, который застает врасплох почти каждого. Научитесь отправлять запросы, обрабатывать любые сбои и создавать небольшой помощник, который можно будет использовать повторно.

9 мин чтения
Учебное пособие по JavaScript Fetch API: GET, POST, обработка ошибок и таймауты

Главное

  • fetch() возвращает обещание для Response, а чтение тела занимает секунду await.
  • Ошибки HTTP, такие как 404 и 500 , не отклоняются, поэтому всегда проверяйте response.ok.
  • Чтобы отправить JSON, используйте JSON.stringify и установите заголовок Content-Type.
  • У Fetch нет опции тайм-аута по умолчанию, поэтому используйте AbortSignal.timeout().

Большинство современных веб-приложений постоянно взаимодействуют с сервером. JavaScript Fetch API — это стандартный способ сделать это, он встроен в браузеры, а также в Node.js 18 и более поздних версий, поэтому устанавливать нечего.

Базовое использование занимает две строки, однако многие руководства останавливаются на этом и опускают ту часть, которая вызывает реальные ошибки: обработку сбоев. Мы протестировали примеры в этом руководстве на небольшом локальном сервере Node.js 24, и показанный результат получен в результате этого запуска. example.com в коде обозначает ваш собственный API. Если обещания для вас новы, начните с объяснения обещаний JavaScript.

Что такое API-интерфейс Fetch?

Fetch — это основанный на обещаниях интерфейс для выполнения HTTP-запросов. Он заменил старый метод, управляемый обратными вызовами XMLHttpRequest, и теперь многие проекты используют его вместо добавления библиотеки для простых вызовов.

Особенность Получить Аксиос (библиотека)
Установка Встроенный Добавлено как зависимость
Тело JSON Стрингифицируйте сами Автоматический
Разобрать ответ JSON Позвонить response.json() Автоматический
Ошибки HTTP отклоняются? Нет Да, по умолчанию
Тайм-аут Через AbortSignal timeout вариант

GET-запрос

Fetch по умолчанию выполняет запрос GET. Есть два шага, и каждый из них требует await: сначала приходят заголовки ответа, а затем вы читаете тело.

const response = await fetch("https://example.com/users/1");
const user = await response.json();

console.log(user);

// { id: 1, name: 'Asha' }

Эти два шага существуют, потому что тело может быть большим и приходить позже заголовков. В скрипте браузера для верхнего уровня await нужен модуль, поэтому вы обычно помещаете его в функцию async. См. наше руководство по асинхронности/ожиданию JavaScript.

Объект ответа

Прежде чем читать тело, вы можете проверить ответ:

console.log(response.status, response.ok, response.headers.get("content-type"));

// 200 true application/json
Свойство или метод Дает вам
response.ok true для статусов с 200 по 299
response.status Код состояния, например 404
response.headers.get(name) Один заголовок ответа
response.json() Тело анализируется как JSON.
response.text() Тело как струна
response.blob() Двоичные данные, такие как изображение

Тело можно прочитать только один раз. Вызов json() во второй раз в нашем тесте не удался:

await res.json();
await res.json();

// TypeError: Body is unusable: Body has already been read

Если вам нужно прочитать его дважды, сначала вызовите response.clone().

Большой сюрприз: ошибка 404 не выдает

Это самое главное в этой статье. Мы запросили пользователя, которого не существует:

const res = await fetch("https://example.com/users/999");
console.log(res.status, res.ok);

// 404 false

Никаких исключений не было. Что касается выборки, запрос сработал: сервер был достигнут, и он ответил. Промис отклоняется только тогда, когда вообще не приходит никакого полезного ответа, как в случае сбоя сети. Итак, в таком коде есть скрытая ошибка:

try {
  const res = await fetch(url);
  const data = await res.json();   // may be an error payload
  showUser(data);                  // runs anyway for 404 and 500
} catch (error) {
  showError();                     // does not run for 404 or 500
}

Ознакомьтесь с нашей шпаргалкой по кодам статуса HTTP, чтобы узнать, что означает каждый код.

Многоразовый помощник

Не повторяйте эту проверку везде. Оберните его один раз:

async function getJson(url, options) {
  const response = await fetch(url, options);
  if (!response.ok) {
    throw new Error(`Request failed with status ${response.status}`);
  }
  return response.json();
}

try {
  await getJson("https://example.com/users/999");
} catch (error) {
  console.log("caught:", error.message);
}

// caught: Request failed with status 404

Теперь ошибки HTTP и сетевые ошибки оказываются в одном и том же catch. Эту небольшую функцию стоит иметь в каждом проекте. Реальная версия также может считывать сообщение об ошибке из тела ответа и обрабатывать ответ 204 No Content, в котором нет JSON для анализа.

POST-данные в формате JSON

Передайте объект параметров в качестве второго аргумента. Для JSON вам необходимо сделать две вещи самостоятельно: преобразовать данные в строку и установить заголовок.

const created = await getJson("https://example.com/users", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ name: "Ben" }),
});

console.log(created);

// { id: 2, name: 'Ben', type: 'application/json' }

Наш тестовый сервер вернул полученный тип контента, подтвердив получение заголовка. Забывание этого заголовка является распространенной причиной запутанных ошибок сервера, поскольку многие платформы анализируют JSON только тогда, когда он объявлен. Чтобы загрузить форму или файлы, передайте объект FormData в качестве тела и не устанавливайте Content-Type, поскольку браузеру необходимо самому добавить граничное значение.

Другие методы и варианты

Вариант Пример Цель
метод "PUT", "PATCH", "DELETE" HTTP-метод
заголовки { Авторизация: "Носитель..." } Заголовки запросов
тело JSON.stringify(data) Тело запроса
сигнал AbortSignal.timeout(5000) Отмена
полномочия "включить" Отправка файлов cookie из разных источников
кэш "без магазина" Поведение кэша браузера

Выбираете между REST и другими стилями API? Наше сравнение REST и GraphQL показывает, насколько fetch подходит для каждого из них.

Строки запроса

Не создавайте строки запроса путем объединения текста, поскольку специальные символы разрушают их. URLSearchParams обрабатывает кодировку за вас:

const params = new URLSearchParams({ q: "red shoes", page: 2 });
console.log(params.toString());

// q=red+shoes&page=2

await getJson(`https://example.com/search?${params}`);

// { q: 'red shoes', page: '2' }

Сервер получил red shoes правильно, место было восстановлено.

Тайм-ауты и отмена

Fetch будет долго ждать на медленном сервере, если вы не укажете иное. AbortSignal.timeout() устанавливает предел. Конечная точка нашего теста заняла две секунды при пределе в 200 миллисекунд:

try {
  await fetch("https://example.com/slow", { signal: AbortSignal.timeout(200) });
} catch (error) {
  console.log(error.name);
}

// TimeoutError

Для отмены вручную, например, когда пользователь покидает страницу или вводит новый поисковый запрос, используйте AbortController:

const controller = new AbortController();
const pending = fetch("https://example.com/slow", { signal: controller.signal });

controller.abort();

try {
  await pending;
} catch (error) {
  console.log(error.name);
}

// AbortError

Чтобы выполнить несколько запросов одновременно, используйте Promise.all, что намного быстрее, чем ожидать их по одному:

const [user, search] = await Promise.all([
  getJson("https://example.com/users/1"),
  getJson("https://example.com/search?q=a&page=1"),
]);

Всякий вид неудачи

Вот как выглядел каждый сбой в нашем тесте, а также как их отличить:

Ситуация Что происходит Как это обнаружить
Сервер возвращает 404 или 500. Обещание выполняется response.ok неверно
Сервер не может быть достигнут Отклоняется с TypeError поймать
Тайм-аут достигнут Отклоняется с TimeoutError error.name
Отменено вручную Отклоняется с AbortError error.name
Тело недействительно в формате JSON. json() отклоняет с помощью SyntaxError поймать

Последний ряд часто встречается в производстве. Прокси-сервер, возвращающий код 502, часто отправляет страницу с ошибкой HTML. Мы воспроизвели это, и res.json() бросил SyntaxError. Проверка response.ok перед анализом означает, что вы сообщаете о реальной проблеме, а не о запутанной ошибке анализа.

Совет. Специально проверьте эти пути отказа. Инструменты разработчика браузера могут имитировать автономный режим, а инструменты тестирования могут имитировать ответ 500. В нашем руководстве по тестированию API с помощью Postman рассматривается проверка стороны API.

CORS и учетные данные

В браузере запрос от одного источника к другому регулируется CORS, правилами совместного использования ресурсов между источниками. Если вы видите ошибку с упоминанием Access-Control-Allow-Origin, исправление принадлежит серверу, который должен разрешить ваш сайт. В вашем JavaScript сбой отображается только как общий TypeError, поэтому посмотрите на консоль браузера, чтобы узнать истинную причину. Node.js не применяет CORS, поэтому запрос, который работает в сценарии, все равно может завершиться неудачей в браузере.

По умолчанию браузеры не отправляют файлы cookie при запросах между источниками. Установите credentials: "include", если они вам нужны, и убедитесь, что сервер это разрешает. Никогда не помещайте секретные ключи API в JavaScript браузера, поскольку их может прочитать любой. Держите их на своем сервере.

Распространенные ошибки

  • Не проверяется. response.ok. Ответы об ошибках рассматриваются как успешные.
  • Забывание второго await. response.json() также возвращает обещание.
  • Забывание JSON.stringify. Передача объекта по мере отправки тела [object Object].
  • Настройка Content-Type с FormData. Это нарушает границу, поэтому оставьте это.
  • Отсутствие тайм-аута. Зависший запрос может привести к тому, что счетчик страницы будет работать бесконечно.
  • Разбор JSON на предмет пустого ответа. У 204 нет тела, и json() выдаст ошибку.

Итоги

Fetch прост, если вы помните его главное правило: ответ — это не то же самое, что успех. Скопируйте небольшой помощник в свой проект, добавьте тайм-аут и проверьте пути отказа. В качестве следующего шага создайте крошечную страницу, которая загружает данные из API, отображает четкое сообщение об ошибке и позволяет пользователю отменить медленный поиск.

Часто задаваемые вопросы

Выдает ли fetch ошибку 404?

Нет. Выборка отклоняется только в том случае, если ответ не получен, например, при сбое сети. На наличие ошибок HTTP проверьте файл response.ok или ответ.status самостоятельно.

Как отправить JSON с помощью извлечения?

Установите метод POST, добавьте заголовок Content-Type приложения/json и передайте данные через JSON.stringify в качестве тела.

Зачем мне два ожидания при извлечении?

Первый разрешается после получения заголовков ответа. Второй ожидает загрузки и анализа тела, что может произойти позже.

Как установить тайм-аут при получении?

Сигнал пропуска: AbortSignal.timeout(5000) в настройках. Затем запрос отклоняется с ошибкой TimeoutError, если он занимает больше миллисекунд.

Доступна ли выборка в Node.js?

Да. Fetch доступен по всему миру в Node.js 18 и более поздних версиях. Для более старых версий требуется пакет, хотя правила CORS применяются только в браузерах.

Продолжайте учиться

Работайте с Stack Quora

Нужна помощь с тестированием, WordPress или SEO?

Мы помогаем командам выпускать лучшее программное обеспечение и развивать свои сайты. Расскажите нам, над чем вы работаете, и мы предложим четкий следующий шаг.

Продолжайте читать

Больше руководств по тестирование, искусственный интеллект и современные разработки

Понравилась эта статья? Выберите тему и сразу приступайте к нашим новейшим руководствам.

Искусственный интеллект

Объяснение галлюцинаций искусственного интеллекта: почему языковые модели все выдумывают и как их уменьшить

Галлюцинации ИИ объяснили: что это такое, почему языковые модели их создают, распространенные типы, как уменьшить их с помощью заземления и подсказо…

Читать статью →
DevOps

Объяснение переменных среды: файлы .env, секреты и правильно выполненная конфигурация

Переменные среды объясняются на примерах Python, которые мы запускали: их чтение и установка, почему каждое значение является строкой, файлы .env, н…

Читать статью →
Разработка ПО

Объяснение ограничения скорости API: алгоритмы, заголовки и обработка ошибок 429

Ограничение скорости API объясняется с помощью проведенного нами моделирования: сегмент токенов, фиксированное окно, скользящее окно, 429 ответов, з…

Читать статью →
Автоматизация тестирования

Издевательство в Python: unittest.mock, патч и ошибки, из-за которых тесты лгут

Издевательство на Python с помощью unittest.mock, протестировано: Mock и return_value, Side_effect, исправление использования имени, спецификация и …

Читать статью →
Тестирование ПО

Объяснение покрытия кода: покрытие линий или ветвей и что на самом деле означает 100%

Покрытие кода объяснено с помощью реального запуска покрытия.py: покрытие строк, ветвей и условий, чтение отчета, почему 100%-ное покрытие все еще м…

Читать статью →
Базы данных и SQL

DELETE, TRUNCATE и DROP в SQL: различия, откат и когда использовать каждый из них

Объяснение DELETE, TRUNCATE и DROP на примере протестированного SQL: что каждый из них удаляет, откат, триггеры, сброс идентификаторов, скорость и ч…

Читать статью →
Базы данных и SQL

Объяснение представлений SQL: создавайте, используйте и избегайте ловушек, с примерами

Представления SQL, объясненные с помощью запросов, которые мы выполняли: создание представления, результаты в реальном времени, скрытие столбцов, пр…

Читать статью →
Разработка ПО

Интерфейс TypeScript и тип: реальные различия, протестированные с помощью компилятора

Интерфейс TypeScript против типа, проверенный реальным компилятором: что могут делать оба, что может делать только один, слияние объявлений, расшире…

Читать статью →
Разработка ПО

Объяснение Python *args и **kwargs: гибкие функции с понятными примерами

Python *args и **kwargs, объясненные с помощью кода, который мы запускали: упаковка и распаковка, порядок параметров, аргументы только по ключевым с…

Читать статью →
Разработка ПО

Лямбда-функции Python: синтаксис, реальное использование и когда их не следует использовать

Лямбда-функции Python, объясненные с помощью кода, который мы запускали: синтаксис, сортировка с помощью ключа, карты и фильтра, замыкания, ловушка …

Читать статью →
Искусственный интеллект

Что такое ИИ-агенты? Как они работают: можно запустить простой цикл агента

Что такое агенты ИИ? Простое руководство по циклу агента, инструментам, памяти и ограничениям, с небольшим циклом Python, который мы запустили, реал…

Читать статью →
DevOps

Мониторинг и наблюдаемость: реальная разница с журналами, метриками и трассировками

Объяснение мониторинга и наблюдаемости: известные и неизвестные сбои, журналы, метрики и трассировки, пошаговое руководство по инцидентам при оформл…

Читать статью →
DevOps

Docker Volumes против Bind Mounts: правильное сохранение данных контейнера

Объяснение томов Docker и монтирования привязки: почему исчезают данные контейнера, именованные тома, монтирование привязки, tmpfs, примеры создания…

Читать статью →
Автоматизация тестирования

TDD против BDD: ключевые различия, одна функция, созданная для обоих способов, и когда использовать каждый

TDD и BDD объясняются с помощью одной функции скидки, созданной в обоих направлениях: красно-зеленый рефакторинг с кодом, который мы запускали, сцен…

Читать статью →
Тестирование ПО

Пользовательское приемочное тестирование (UAT): процесс, контрольный список и реальные примеры

Приемочное тестирование пользователей объяснило: кто его проводит, чем оно отличается от контроля качества, семиэтапный процесс, шаблон тестового сц…

Читать статью →
Базы данных и SQL

Объяснение значений NULL в SQL: IS NULL, COALESCE, NULLIF и ловушки, которых следует избегать

Значения SQL NULL объяснены с помощью запросов, которые мы выполнили: трехзначная логика, IS NULL, COALESCE, NULLIF, как агрегаты, соединения и сорт…

Читать статью →
Базы данных и SQL

Оператор SQL CASE WHEN: синтаксис, реальные примеры и распространенные ошибки

SQL CASE WHEN объяснен с помощью запросов, которые мы выполняли: простые формы и формы для поиска, порядок условий, повороты с помощью SUM, трюки CO…

Читать статью →
Разработка ПО

Что такое JWT? Веб-токены JSON, объясненные на рабочем примере

Что такое JWT? Объяснение JSON Web Tokens: три части: токен, созданный и измененный в коде, который мы запускали, JWT и сеансы, хранилище, токены об…

Читать статью →
Разработка ПО

Объяснение цикла событий JavaScript: стек вызовов, микрозадачи и таймеры с примерами

Цикл событий JavaScript объясняется с помощью кода, который мы запускали: стек вызовов, очереди задач и микрозадач, почему setTimeout 0 не является …

Читать статью →
Разработка ПО

Генераторы Python и объяснение доходности: экономьте память с помощью реальных примеров

Генераторы Python и доходность, объясненные с помощью кода, который мы запускали: как они приостанавливаются и возобновляются, измеряют экономию пам…

Читать статью →
Искусственный интеллект

Что такое вложения? Простое объяснение векторов и косинусного сходства

Что такое вложения? Простое руководство по векторам, косинусному подобию и семантическому поиску с небольшим примером, который мы использовали, общи…

Читать статью →
DevOps

Сине-зеленое и канареечное развертывание: различия, компромиссы и как выбрать

Объяснение сине-зеленого и канареечного развертывания: как каждый из них работает, стоимость, риски и откат, стабильное группирование пользователей,…

Читать статью →
Автоматизация тестирования

Ненадежные тесты: что их вызывает и как их исправить навсегда

Ненадежные тесты объясняются на демонстрациях, которые мы запускали: основные причины, способы подтверждения и диагностики, правильные исправления в…

Читать статью →
Тестирование ПО

Нагрузочное тестирование и стресс-тестирование: различия, метрики и примеры k6

Объяснение нагрузочного и стресс-тестирования: что доказывает каждое из них, тесты на всплески и выдержки, важные метрики, почему средние значения в…

Читать статью →
Тестирование ПО

Тестовый пример и тестовый сценарий: ключевые различия, примеры и когда использовать каждый

Объяснение тестового случая и тестового сценария: четкие определения, параллельная таблица, одна функция сброса пароля, взятая из сценариев в случаи…

Читать статью →
Базы данных и SQL

Оптимизация SQL-запросов: чтение планов выполнения и исправление медленных запросов с указанием времени

Оптимизация SQL-запросов проверена на миллионе строк: читайте планы выполнения, добавляйте правильные индексы, исправляйте неразмещаемые фильтры, ис…

Читать статью →
Базы данных и SQL

SQL UNION против UNION ALL: различия, примеры и проверка производительности

SQL UNION и UNION ALL объяснены с помощью запросов, которые мы выполнили: дубликаты, правила, которым следуют оба, реальная ошибка данных, измеренна…

Читать статью →
Разработка ПО

Учебное пособие по API JavaScript Fetch: GET, POST, обработка ошибок и тайм-ауты

Учебное пособие по API JavaScript Fetch, протестированное на локальном сервере: GET и POST, почему не выдается ошибка 404, многоразовый помощник, ст…

Читать статью →
Разработка ПО

Обработка файлов Python: чтение, запись, CSV, JSON и pathlib с примерами

Обработка файлов Python объясняется с помощью кода, который мы запускали: открытые режимы, чтение больших файлов, CSV, JSON, pathlib, двоичные файлы…

Читать статью →
Разработка ПО

Классы и объекты Python: учебник ООП с реальными примерами

Классы и объекты Python, объясненные с помощью кода, который мы запускали: __init__, методы, атрибуты класса и экземпляра, наследование, свойства, м…

Читать статью →
Искусственный интеллект

Что такое большая языковая модель? Как работают LLM, объяснено без шумихи

Что такое большая языковая модель? LLM объясняется простым языком: токены, встраивания, внимание, обучение, температурные и контекстные окна, крошеч…

Читать статью →
DevOps

Команды Linux для начинающих: основное руководство по терминалу с примерами

Команды Linux для начинающих, сгруппированные по задачам: навигация, файлы, просмотр журналов, grep, каналы, разрешения, процессы и архивы, с практи…

Читать статью →
Автоматизация тестирования

Selenium vs Playwright: ключевые различия, сравнение кода и что выбрать

Сравнение Selenium и Playwright: архитектура, ожидание, поддержка браузера и языка, отладка, одинаковый тест в обоих инструментах, советы по миграци…

Читать статью →
Тестирование ПО

Разделение эквивалентности: метод проектирования тестов, объясненный на рабочих примерах

Объяснение эквивалентного разделения: как найти действительные и недействительные разделы, рабочие примеры для возрастов, паролей и купонов, проведе…

Читать статью →
Тестирование ПО

Серьезность и приоритет в тестировании программного обеспечения: различия, матрица и реальные примеры

Объяснение серьезности и приоритета при тестировании программного обеспечения: четкие определения, четырехсторонняя матрица с примерами, шкалы уровн…

Читать статью →
Базы данных и SQL

Учебное пособие по подзапросам SQL: типы, коррелирующие подзапросы и EXISTS с примерами

Руководство по подзапросам SQL с выполненными нами запросами: скалярные подзапросы, IN, FROM и SELECT, коррелированные подзапросы, EXISTS, ловушка N…

Читать статью →
Базы данных и SQL

Объяснение транзакций SQL и ACID: COMMIT, ROLLBACK и уровни изоляции

Транзакции SQL и ACID, объясненные с помощью банковского перевода, который мы выполнили: COMMIT, ROLLBACK, точки сохранения, блокировки, уровни изол…

Читать статью →
Разработка ПО

Git Commands Cheat Sheet: The Commands You Actually Use, With Examples

Шпаргалка по командам Git, сгруппированная по задачам: настройка, промежуточный этап, ветки, удаленные устройства, тайник, история и исправление оши…

Читать статью →
Разработка ПО

Объяснение промисов в JavaScript: then, catch, Promise.all и распространенные ошибки

Обещания JavaScript, объясненные с помощью кода, который мы запускали: состояния, цепочки then и catch, обработка ошибок, Promise.all, allSettled, R…

Читать статью →
Разработка ПО

Учебное пособие по словарю Python: методы, примеры и общие шаблоны

Учебное пособие по словарю Python с кодом, который мы выполнили: создание, чтение и обновление словарей, ключевые методы, слияние, понимание, шаблон…

Читать статью →
Искусственный интеллект

Что такое РАГ? Генерация с расширенным поиском, объясненная на рабочем примере

Что такое РАГ? Retrieval-augmented generation explained step by step: indexing, chunking, embeddings, retrieval, a small working Python example, eva…

Читать статью →
DevOps

Учебное пособие по Terraform для начинающих: инфраструктура как код от первого файла до модулей

Учебное пособие по Terraform для начинающих: начните без облачной учетной записи, изучите инициализацию, планирование и применение, затем переменные…

Читать статью →
DevOps

Docker и Kubernetes: ключевые различия, как они работают вместе и что вам нужно

Объяснение Docker и Kubernetes: что делает каждый из них, одно и то же приложение работает с обоими, сравнение Docker Compose и Swarm, изменение doc…

Читать статью →
Автоматизация тестирования

Учебное пособие по Pytest для начинающих: фикстуры, параметризация и реальные примеры

Учебное пособие по pytest для начинающих с тестами, которые мы запускали на pytest 9.2: утверждения, фикстуры, параметризация, conftest, маркеры, tm…

Читать статью →
Тестирование ПО

Жизненный цикл тестирования программного обеспечения (STLC): 6 этапов, критерии входа и выхода, пример

Объясняется жизненный цикл тестирования программного обеспечения: шесть этапов STLC с критериями входа и выхода, результаты, пример проработанной фу…

Читать статью →
Разработка ПО

Git merge vs rebase: отличия, примеры и когда что использовать

Git merge vs rebase с реальным выводом log, сравнительной таблицей, золотым правилом rebase и безопасным рабочим процессом для команды.

Читать статью →
Разработка ПО

Генераторы списков в Python: синтаксис, примеры и когда их избегать

Генераторы списков в Python: синтаксис, фильтры, if-else, вложенные циклы, измеренное время и случаи, когда обычный цикл for лучше.

Читать статью →
Базы данных и SQL

SQL JOIN: объяснение с примерами (Inner, Left, Right, Full)

Разберите SQL JOIN шаг за шагом на примерах таблиц и запросов: INNER, LEFT, RIGHT, FULL, CROSS и SELF, а также частые ошибки и советы по производите…

Читать статью →