Исчерпывающее руководство по JavaScript Notifications API
Notifications API — веб-технология, позволяющая разработчикам отправлять уведомления и управлять ими прямо из веб-приложений.
Введение в Notifications API
Notifications API позволяет веб-приложению отображать системные сообщения за пределами вкладки браузера — небольшие всплывающие окна, которые операционная система показывает в углу экрана. Поскольку они появляются даже когда пользователь переключился на другую вкладку или приложение, уведомления — это прямой способ донести срочную информацию: новое сообщение в чате, завершённая загрузка, напоминание календаря.
На этой странице рассматривается полный жизненный цикл: проверка доступности API, запрос разрешения у пользователя, создание и настройка уведомлений, реакция на клики и отображение уведомлений из service worker, чтобы они продолжали работать после закрытия страницы. В конце изложены правила, не позволяющие уведомлениям стать навязчивыми.
Несколько фактов, которые стоит учесть перед написанием первой строки кода:
- Уведомления требуют явного разрешения от пользователя. Показать их нельзя, пока разрешение не равно
granted. - Они работают только в безопасном контексте (
https://илиhttp://localhostпри разработке). - Внешний вид и поведение уведомления определяются операционной системой, а не вашим CSS. Вы предоставляете содержимое; ОС решает, как его отображать.
Проверка поддержки
Всегда выполняйте определение возможностей перед использованием API, чтобы код корректно деградировал в средах, где он недоступен (старые браузеры, некоторые встроенные webview и серверный рендеринг):
if ('Notification' in window) {
// The Notifications API is available
} else {
console.log('This browser does not support notifications.');
}Понимание разрешений
Состояние разрешения хранится в статическом свойстве Notification.permission и принимает одно из трёх строковых значений:
'granted'— пользователь разрешил уведомления; можно их показывать.'denied'— пользователь заблокировал их; попытки показать уведомление молча игнорируются.'default'— пользователь ещё не принял решение; это значение обрабатывается как'denied', пока вы не спросите.
Запросить разрешение можно с помощью Notification.requestPermission(). Метод возвращает промис, который разрешается в итоговую строку разрешения:
Notification.requestPermission().then((permission) => {
console.log('Permission:', permission); // 'granted', 'denied', or 'default'
});Браузеры позволяют вызывать requestPermission() только в ответ на жест пользователя, например нажатие кнопки. Автоматический запрос разрешения при загрузке страницы широко блокируется и ухудшает пользовательский опыт — дожидайтесь момента, когда пользователь совершит действие, объясняющее, зачем нужны уведомления.
Надёжный паттерн сначала проверяет текущее состояние и запрашивает разрешение только тогда, когда решение ещё не принято ('default'):
async function ensurePermission() {
if (Notification.permission === 'granted') {
return true;
}
if (Notification.permission === 'denied') {
return false; // can't re-prompt; the user must change it in browser settings
}
const permission = await Notification.requestPermission();
return permission === 'granted';
}Форма на основе промисов хорошо сочетается с async/await и общим Promise API.
Создание и отображение уведомлений
Когда разрешение равно granted, создайте уведомление с помощью конструктора Notification. Первый аргумент — заголовок (обязательный); второй — необязательный объект параметров.
if (Notification.permission === 'granted') {
new Notification('Hello, world!', {
body: 'Here is the body of the notification.',
icon: '/icon-192.png'
});
}Уведомление появляется в момент создания объекта — отдельный метод «показать» вызывать не нужно.
Основные параметры
Объект параметров принимает множество полей. Наиболее полезные из них:
| Параметр | Тип | Назначение |
|---|---|---|
body | string | Основной текст, отображаемый под заголовком. |
icon | URL | Изображение рядом с уведомлением. |
badge | URL | Небольшая монохромная иконка для устройств с ограниченным пространством (преимущественно мобильных). |
image | URL | Более крупное изображение в теле уведомления. |
tag | string | Идентификатор для группировки уведомлений; новое уведомление с тем же тегом заменяет старое. |
data | any | Произвольные данные, доступные в обработчике клика. |
silent | boolean | При значении true отключает звук и вибрацию. |
requireInteraction | boolean | Удерживает уведомление на экране до явного закрытия пользователем (для десктопа). |
lang / dir | string | Подсказки о языке и направлении текста. |
new Notification('New message', {
body: 'You have 1 unread message from Alex.',
icon: '/icon-192.png',
tag: 'chat-alex', // replacing an earlier "Alex" notification
data: { conversationId: 42 },
requireInteraction: true
});Предотвращение спама уведомлений с помощью tag
Параметр tag — простейший способ избежать накопления дубликатов. Если от одного человека пришло три сообщения, повторное использование одного тега означает, что пользователь видит одно обновлённое уведомление вместо трёх:
function notifyUnread(count) {
new Notification('Inbox', {
body: `You have ${count} unread messages.`,
tag: 'inbox-count' // each call updates the same notification
});
}События уведомлений
Экземпляр Notification генерирует события, которые можно отслеживать. Наиболее важное — click, возникающее, когда пользователь активирует уведомление:
const notification = new Notification('Interactive Notification', {
body: 'Click me to do something',
icon: '/icon-192.png'
});
notification.onclick = (event) => {
event.preventDefault(); // stop the browser's default focus behavior
window.open('https://example.com', '_blank');
notification.close(); // remove the notification once handled
};Другие доступные события: show (отображено), error (ошибка отображения) и close (закрыто). Обработчики можно также подключать через addEventListener — общий паттерн описан в разделе обработка событий в DOM.
Программное закрытие уведомлений
Вызовите close(), чтобы закрыть уведомление самостоятельно — удобно для удаления уведомления «загружается…» после завершения загрузки:
const note = new Notification('Downloading…', { tag: 'download' });
// later, when the work is done:
setTimeout(() => note.close(), 4000);Беззвучные уведомления
Установите silent: true, чтобы показывать уведомление без звука и вибрации — подходит для низкоприоритетных фоновых обновлений:
new Notification('Silent Notification', {
body: 'This is a silent notification.',
silent: true
});Уведомления из service worker
Стандартный конструктор Notification работает только пока страница открыта. Чтобы доставлять уведомления, когда сайт находится в фоне — или в ответ на серверное push-сообщение — показывайте их из service worker с помощью ServiceWorkerRegistration.showNotification():
// In the page: ask the service worker to show a notification
navigator.serviceWorker.ready.then((registration) => {
registration.showNotification('Background-capable notification', {
body: 'This can be shown even after the tab is closed.',
icon: '/icon-192.png',
actions: [
{ action: 'open', title: 'Open' },
{ action: 'dismiss', title: 'Dismiss' }
]
});
});Уведомления service worker также поддерживают кнопки действий (массив actions), которые простой конструктор не поддерживает. Обработка кликов выполняется внутри самого service worker:
// In the service worker (sw.js)
self.addEventListener('notificationclick', (event) => {
event.notification.close();
if (event.action === 'open') {
event.waitUntil(clients.openWindow('/inbox'));
}
});Этот путь через service worker лежит в основе настоящего web push: сервер отправляет сообщение, Push API пробуждает service worker, и воркер вызывает showNotification().
Поддержка браузерами и особенности
- Только безопасный контекст. Уведомления требуют HTTPS (или
localhost). На страницах сhttp://они работать не будут. - Разрешение сохраняется. Если пользователь выбрал
'denied', повторно запросить разрешение из JavaScript невозможно — необходимо изменить настройки в браузере. Не стоит повторять запросы. - iOS Safari исторически не поддерживал веб-уведомления; поддержка появилась только для сайтов, добавленных на главный экран как PWA. Всегда проверяйте наличие возможности.
- Внешний вид определяется ОС. Не полагайтесь на конкретный размер, положение или оформление — сосредоточьтесь на чётком и лаконичном тексте.
Лучшие практики
Чтобы уведомления оставались полезной функцией, а не тем, что пользователи отключают:
- Запрашивайте разрешение в контексте, после жеста. Просите его тогда, когда пользователь только что совершил действие, делающее уведомления очевидно полезными (например, включил оповещения), но никогда — при первой загрузке.
- Уважайте отказ. Если разрешение равно
'denied', остановитесь. Повторные запросы технически невозможны, а навязчивость в интерфейсе подрывает доверие. - Будьте своевременны и актуальны. Отправляйте только те уведомления, которые пользователь действительно хотел бы получить в данный момент.
- Используйте их экономно. Группируйте с помощью
tag, объединяйте по возможности, и оставляйте уведомления для действительно важного — чрезмерная рассылка приучает пользователей игнорировать или блокировать вас. - Делайте клики значимыми. Клик должен вести пользователя прямо к нужному контенту, а не просто на главную страницу.
Заключение
JavaScript Notifications API позволяет веб-приложениям своевременно доносить системные сообщения до пользователей — как пока страница открыта, так и после её закрытия, через service worker. Рабочий процесс неизменен: определение возможностей, запрос разрешения в ответ на жест пользователя, затем создание уведомлений с помощью конструктора Notification (или showNotification() в воркере) и реакция на события клика. В сочетании с дисциплинированным и экономным использованием уведомления становятся функцией, которую пользователи оставляют включённой, а не спешат отключить.