> Как отправить состояние при закрытии страницы браузера? (JavaScript)
Уровень: senior · Роль: frontend · Категория: Технические вопросы
Компании: elirox
Стек: JavaScript
> Пример ответа
Короткий ответ
Для отправки состояния при закрытии страницы используйте navigator.sendBeacon() - он гарантирует отправку даже при закрытии вкладки. Альтернатива - синхронный XMLHttpRequest в обработчике beforeunload, но он может быть заблокирован браузером. fetch с keepalive: true также работает, но sendBeacon предпочтительнее, так как не блокирует основной поток и гарантирует доставку.
Подробное объяснение
При закрытии страницы браузер завершает выполнение JavaScript, и асинхронные запросы (обычный fetch, XMLHttpRequest) могут быть отменены. Основные события для отслеживания закрытия: beforeunload (срабатывает перед выгрузкой, позволяет отменить закрытие) и unload (срабатывает при выгрузке, но менее надёжен). visibilitychange с document.visibilityState === 'hidden' также подходит, так как срабатывает при переходе на другую вкладку или закрытии.
navigator.sendBeacon() отправляет небольшой объём данных (обычно до 64 КБ) асинхронно, но с гарантией доставки - браузер выполняет запрос даже после завершения страницы. Он использует POST-запрос и не ждёт ответа. Это стандартный механизм для аналитики и логов.
fetch с опцией keepalive: true работает аналогично, но может быть менее эффективным для больших объёмов данных. Синхронный XMLHttpRequest в beforeunload - устаревший подход, который браузеры могут блокировать или показывать предупреждения.
На практике
Наиболее надёжный способ - использовать navigator.sendBeacon() в обработчике beforeunload или visibilitychange. Для критически важных данных (например, сохранение черновика) комбинируйте с периодическим сохранением. Учитывайте, что sendBeacon не поддерживает кастомные заголовки - для них используйте fetch с keepalive. Также проверяйте, что данные не превышают лимит (обычно 64 КБ).
Пример кода
JAVASCRIPT// Отправка состояния при закрытии страницыwindow.addEventListener('beforeunload', () => {const state = {lastSaved: Date.now(),userId: 123,data: 'some important state'};// Используем sendBeacon для гарантированной отправкиconst blob = new Blob([JSON.stringify(state)], { type: 'application/json' });navigator.sendBeacon('/api/save-state', blob);});// Альтернатива с fetch + keepalivewindow.addEventListener('visibilitychange', () => {if (document.visibilityState === 'hidden') {fetch('/api/logout', {method: 'POST',keepalive: true,body: JSON.stringify({ sessionId: 'abc' }),headers: { 'Content-Type': 'application/json' }});}});
Как отвечать на собеседовании
Начните с ключевого решения - navigator.sendBeacon(). Объясните, почему асинхронные запросы не работают при закрытии страницы. Упомяните альтернативы (fetch с keepalive, синхронный XHR) и их ограничения. Подчеркните, что sendBeacon - стандарт для аналитики и логов. Если спросят про объём данных, скажите про лимит 64 КБ. Для больших данных предложите сохранять частями или использовать Service Worker.
Что проверяет интервьюер
- Понимание жизненного цикла страницы и событий выгрузки.
- Знание механизмов гарантированной отправки данных.
- Умение выбирать правильный API под задачу.
- Осведомлённость об ограничениях (размер данных, поддержка заголовков).
- Практический опыт работы с аналитикой и сохранением состояния.
Типичные ошибки
- Использование асинхронного
fetchбезkeepalive- запрос не выполнится. - Полагаться только на
unload- событие может не сработать в мобильных браузерах. - Отправка слишком больших данных через
sendBeacon- запрос будет отклонён. - Использование
beforeunloadдля обязательной отправки - пользователь может отменить закрытие. - Забыть про
visibilitychangeдля случаев, когда вкладка не закрывается, а скрывается.
> Похожие задачи по frontend
В чем разница между async function и обычной функцией в JavaScript?
Как создаются переменные в JavaScript?
Как в SSR составляется состояние для рендера?
В каком порядке срабатывают события при нажатии на кнопку и почему
> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?
Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью