Отмена запросов и поток событий с сервера
AbortController - отмена fetch-запросов
Пользователь ушёл со страницы, ввёл новый поиск, закрыл модальное окно — старый fetch всё ещё ждёт ответ. Без отмены:
- тратится сеть и память;
- устаревший ответ может перезаписать актуальные данные на экране.
Базовый fetch разобран в асинхронном программировании. Здесь — прерывание и односторонний поток с сервера.
AbortController и fetch
AbortController выдаёт сигнал signal. Передайте его в fetch — при вызове abort() запрос прерывается, промис отклоняется с AbortError.
const controller = new AbortController();
const { signal } = controller;
const request = fetch('/api/search?q=js', { signal })
.then((response) => response.json())
.then((data) => renderResults(data))
.catch((error) => {
if (error.name === 'AbortError') {
return; // ожидаемая отмена, не ошибка UX
}
showError(error);
});
// пользователь набрал новый запрос:
controller.abort();
Таймаут
function fetchWithTimeout(url, options = {}, ms = 8000) {
const controller = new AbortController();
const id = setTimeout(() => controller.abort(), ms);
return fetch(url, { ...options, signal: controller.signal }).finally(() => {
clearTimeout(id);
});
}
Один контроллер на компонент
При размонтировании виджета (виджеты на ванильном JS) отменяйте все висящие запросы:
class SearchBox {
constructor(root) {
this.controller = null;
this.root = root;
this.root.querySelector('input').addEventListener('input', () => this.search());
}
search() {
this.controller?.abort();
this.controller = new AbortController();
fetch(`/api/search?q=${encodeURIComponent(this.query)}`, {
signal: this.controller.signal,
})
.then((r) => r.json())
.then((items) => this.render(items))
.catch((e) => {
if (e.name !== 'AbortError') throw e;
});
}
destroy() {
this.controller?.abort();
}
}
Несколько операций
Один signal можно передать в несколько fetch — abort() прервёт все.
EventSource (Server-Sent Events)
SSE — долгоживущее HTTP-соединение, по которому сервер шлёт текстовые события клиенту. Клиент только слушает (в отличие от WebSocket, где канал двусторонний).
const source = new EventSource('/api/notifications/stream');
source.addEventListener('open', () => {
console.log('соединение установлено');
});
source.addEventListener('message', (event) => {
const payload = JSON.parse(event.data);
appendNotification(payload);
});
source.addEventListener('ping', (event) => {
// кастомный тип: сервер шлёт "event: ping\ndata: ...\n\n"
});
source.addEventListener('error', () => {
// браузер переподключится с задержкой (по умолчанию)
});
// при уходе со страницы:
source.close();
На сервере ответ с заголовками Content-Type: text/event-stream, Cache-Control: no-cache, тело в формате:
event: message
data: {"id":1,"text":"Новый заказ"}
| Критерий | SSE (EventSource) | WebSocket |
|---|---|---|
| Направление | сервер → клиент | оба направления |
| Протокол | обычный HTTP | отдельный ws/wss |
| Прокси / CDN | проще | иногда нужны настройки |
| Типичное применение | уведомления, лента, прогресс | чат, игра, совместное редактирование |
Для отправки данных на сервер при SSE используйте обычный fetch POST параллельно с потоком.
Ошибки и CORS
AbortError— не показывать как «сеть недоступна».- SSE с другого origin требует CORS и корректных заголовков; cookies —
withCredentials: trueуEventSource, если нужна сессия. - При закрытии вкладки вызывайте
source.close(), иначе соединение висит до таймаута.
Краткий итог
AbortController — стандартный способ отменить fetch и избежать гонок при быстром вводе. EventSource — простой поток событий с сервера без полноценного WebSocket. Оба дополняют главу про асинхронность, а не заменяют её.
См. также
Другие статьи этого же раздела в боковом меню (как на странице «О разделе»). Основы JavaScript - стандарт ECMAScript, модель выполнения и базовые конструкции языка. JavaScript — это язык программирования, который позволяет создавать интерактивные веб-страницы, серверные приложения и мобильные программы. Для создания массивов используется литеральная нотация. Конструктор Array не применяется. Как работать с HTML-элементами, как их создавать, менять. Простые приложения на JavaScript - базовые сценарии, структура кода и быстрый старт с практическими примерами. Расширения файлов определяют способ обработки кода средой выполнения или компилятором. История JavaScript - происхождение языка, ключевые этапы развития и влияние на современный веб. Такое именование представляет собой соглашение между разработчиками. Классический JavaScript не обеспечивает реальной приватности через подчеркивания. JavaScript содержит набор зарезервированных слов, которые имеют специальное значение в языке. Эти слова нельзя использовать в качестве идентификаторов для переменных, функций или классов. Встроенные функции JavaScript - ключевые методы массивов, строк и объектов для повседневной разработки. Этот шаблон описывает подключение внешних функций, классов или значений из других файлов. Он используется в начале файла и определяет зависимости текущего модуля. JavaScript используется для создания кроссплатформенных мобильных приложений, которые работают на iOS и Android с использованием единой кодовой базы.Основы JavaScript
Что требуется знать перед началом изучения языка программирования JavaScript
Рекомендации по разработке на JavaScript
Работа с HTML в JavaScript
Простые приложения на JavaScript
Форматы JavaScript
История языка JavaScript
Синтаксис и пунктуация в JavaScript
Ключевые слова языка JavaScript
Встроенные функции JavaScript
Структура и подключение JavaScript-кода
Применение JavaScript в вебе и за его пределами