Какие способы обновления данных на клиенте по инициативе сервера существуют
Что проверяют
Знаете ли вы весь спектр от периодического опроса до постоянного соединения и умеете ли выбрать по направлению данных, частоте событий и инфраструктуре. Следом обычно спрашивают, что будет при обрыве связи и как не потерять события, пришедшие за это время.
Как отвечать
Идите от простого к сложному:
- периодический опрос:
fetchпо таймеру раз в несколько секунд. Прост и кэшируется, но задержка равна интервалу, а большинство ответов пустые. В React этоrefetchIntervalв TanStack Query; - long polling: сервер держит запрос, пока не появятся данные, клиент сразу шлёт следующий. Работает везде, но каждое событие стоит полного HTTP-цикла;
- Server-Sent Events:
EventSource, поток текстовых событий по обычному HTTP. Переподключение встроено, а по заголовкуLast-Event-IDсервер дошлёт пропущенное. Ограничения: только GET, свои заголовки задать нельзя. На HTTP/1.1 браузер держит около шести соединений на домен, поэтому SSE лучше отдавать по HTTP/2; - WebSocket: двусторонний канал поверх одного соединения. Нужен, когда клиент тоже часто пишет: чат, совместное редактирование, игры. Heartbeat и переподключение пишете сами или берёте Socket.IO, у которого свой протокол поверх WebSocket;
- Web Push: Push API и Service Worker, доставка даже при закрытой вкладке. Нужны разрешение пользователя и VAPID-ключи;
- WebTransport: поверх HTTP/3, поддержка в браузерах пока неполная.
Для уведомлений и лент обычно хватает SSE. Хороший приём: событие несёт не данные, а сигнал для invalidateQueries, и свежие данные приходят обычным запросом.
Где спотыкаются
Берут WebSocket для односторонней ленты и потом сами пишут переподключение, которое у SSE есть из коробки.
Забывают про прокси. Nginx по умолчанию рвёт соединение без трафика через 60 секунд (proxy_read_timeout) и буферизует ответ, поэтому SSE приходит пачками. Нужны heartbeat и proxy_buffering off или заголовок X-Accel-Buffering: no.
Не думают о пропущенных событиях. После переподключения разницу нужно дочитать по идентификатору или версии, иначе интерфейс тихо расходится с сервером.