Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Подія unload». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**`unload` спрацьовує в той момент, коли документ уже вивантажується з пам'яті браузера: користувач закрив вкладку, натиснув F5, перейшов за посиланням або на іншу сторінку з повним перезавантаженням.** Скасувати перехід у цьому обробнику неможливо, показати діалог теж; браузер не чекає на асинхронні операції, тому `fetch` і `setTimeout` тут не спрацюють. Придатні лише синхронні дії (запис у `localStorage`) або `navigator.sendBeacon()`. У Safari та на iOS `unload` часто взагалі не викликається, тож надійніша сучасна заміна, це `pagehide`. ```javascript window.addEventListener('unload', () => { navigator.sendBeacon('/analytics', JSON.stringify({ event: 'exit' })); }); ``` **Ключове:** `beforeunload`, це «попередити перед виходом», `unload`, це «прибрати за собою після виходу».Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення**`unload`, це подія, яка виникає тоді, коли документ вивантажується з пам'яті браузера.** Вона спрацьовує в самий останній момент життя сторінки, коли зупинити перехід уже не можна, а можна лише швидко прибрати за собою. ## Теорія ### TL;DR - `unload` виникає, коли користувач закриває вкладку, оновлює сторінку (`F5`), переходить за посиланням або на іншу сторінку з повним перезавантаженням. - Зупинити перехід або показати діалог з обробника `unload` неможливо, для цього існує `beforeunload`. - Асинхронні операції (`fetch`, `setTimeout`) не встигають виконатися: браузер їх не чекає. - Працюють лише синхронні дії, наприклад запис у `localStorage`, плюс `navigator.sendBeacon()`. - У частині браузерів (Safari, iOS) `unload` може взагалі не викликатися; сучасна заміна, це `pagehide`. - Типові задачі: логування виходу, збереження стану, закриття WebSocket-з'єднань. ### Швидкий приклад ```javascript window.addEventListener('unload', () => { // спрацює в самий останній момент, коли сторінка вже йде з пам'яті console.log('Сторінка вивантажується...'); }); ``` ### Коли спрацьовує `unload` Подія виникає, коли документ виходить з пам'яті браузера. На практиці це означає, що користувач: - закриває вкладку; - оновлює сторінку (`F5`); - переходить за іншим посиланням; - або переходить на іншу сторінку в SPA при повному перезавантаженні. Типові сценарії застосування: - надсилання статистики або логів «перед виходом» користувача; - збереження даних у `localStorage` / `sessionStorage`; - закриття з'єднань, WebSocket, звільнення ресурсів. Наприклад, зберегти час останнього візиту: ```javascript window.addEventListener('unload', () => { localStorage.setItem('lastVisited', new Date().toISOString()); }); ``` ### `unload` це не `beforeunload` Дві події легко переплутати, але вони вирішують різні задачі: `beforeunload` спрацьовує *перед* вивантаженням і ще може його зупинити, `unload` спрацьовує *під час* вивантаження, коли вже пізно щось вирішувати. | Властивість | `beforeunload` | `unload` | | --- | --- | --- | | Коли спрацьовує | Перед вивантаженням | Під час вивантаження | | Чи можна зупинити вихід | Так (`preventDefault()`) | Ні | | Чи можна показати попередження | Так | Ні | | Чи можна виконувати код | Так, але обмежено | Дуже обмежено | | Типові задачі | Попередити про незбережені дані | Очищення, логування | ### Обмеження і нюанси Сучасні браузери сильно обмежують `unload`, щоб не гальмувати закриття сторінок: - **Асинхронні дії (`fetch`, `setTimeout`) не працюють**, браузер не чекає їхнього завершення. - Не можна показати діалог або модальне вікно. - Працюють **тільки синхронні** операції, наприклад запис у `localStorage`, або `navigator.sendBeacon()`. - У деяких браузерах (Safari, iOS) `unload` **взагалі не викликається**, там використовують `pagehide`. Додатковий мінус: сама наявність обробника `unload` (як і `beforeunload`) робить сторінку непридатною для bfcache, кеша «назад/вперед», тому повернення на неї стає повільнішим. ### Рекомендована альтернатива: `pagehide` `pagehide`, це сучасніша і надійніша подія, особливо в мобільних браузерах: ```javascript window.addEventListener('pagehide', (event) => { // event.persisted === true означає, що сторінка йде в bfcache console.log('Сторінка прихована або вивантажена'); }); ``` Вона працює навіть при переході на іншу вкладку і спрацьовує надійніше, ніж `unload`. Для аналітики часто беруть ще й `visibilitychange` зі станом `hidden`, бо на мобільних це єдиний момент, який гарантовано настане. ### Надсилання аналітики при закритті сторінки Єдиний безпечний спосіб відправити дані на сервер у момент закриття, це `navigator.sendBeacon()`: запит ставиться в чергу браузера і буде доставлений навіть після того, як сторінка зникне. ```javascript window.addEventListener('unload', () => { navigator.sendBeacon('/analytics', JSON.stringify({ event: 'exit' })); }); ``` Формально виклик асинхронний, але браузер бере доставку на себе, тому дані не губляться, як це сталося б зі звичайним `fetch`. Підсумок по події: | Що робить | Подія `unload` | | --- | --- | | Коли спрацьовує | Коли користувач залишає сторінку | | Чи можна зупинити перехід | Ні | | Для чого підходить | Очищення, логи, збереження стану | | Чи працює асинхронно | Ні (тільки синхронно або через `sendBeacon`) | | Сучасна альтернатива | `pagehide` | | Часте застосування | Аналітика, збереження стану | > **Запам'ятай просто:** > `beforeunload`, це «попередити перед виходом», > `unload`, це «прибрати за собою після виходу». ### Типові помилки - **Робити `fetch` у `unload`.** Браузер обриває запит разом зі сторінкою; потрібен `navigator.sendBeacon()`. - **Розраховувати на `setTimeout` або проміси.** Мікро- і макрозадачі вже не виконаються, документ іде з пам'яті. - **Намагатися скасувати перехід у `unload`.** `preventDefault()` тут не має ефекту, це задача `beforeunload`. - **Покладатися на `unload` в мобільному Safari.** Подія може не викликатися взагалі, стан буде втрачено; слухайте `pagehide` або `visibilitychange`. - **Забувати, що обробник ламає bfcache.** Сторінка перестає кешуватися, і повернення «назад» відпрацьовує повільніше. - **Складна робота в обробнику.** Довгий синхронний код відчутно затримує закриття вкладки для користувача.Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.