通知 · API
Notification 接口
发布于
Notification 是代表一条已显示通知的对象。new Notification(title, options) 从页面或专用 worker 创建并立即显示一条非持久通知;同一个接口在持久通知的场景下以 event.notification 交给 Service Worker。它的实例属性映射创建时传入的选项,事件则报告显示、激活、关闭和失败。
new Notification(title)new Notification(title, options)notification.close()Notification.permissionNotification.maxActions构造函数暴露在 Window 以及专用和共享 worker 上,在 ServiceWorkerGlobalScope 内抛出,那里的替代是 self.registration.showNotification()。桌面端支持为 Chrome 20、Firefox 22、Safari 7、Edge 14(BCD api.Notification.Notification)。移动端构造函数虽然存在,但在 Chrome for Android、Samsung Internet 和 iOS 上的 Safari 中无法使用(细节见「异常」),所以 PWA 把它当作仅限桌面的便利。
实例成员均为只读,映射构造函数的 options。
| 成员 | 类型 | 含义 |
|---|---|---|
title、body、icon、image、badge |
string | 创建时传入的文本与图片 URL。缺省的选项读作 ""。 |
tag |
string | 替换键。同一源上后来带相同 tag 的通知会替换这一条。 |
data |
any | 作为 options.data 传入的可结构化克隆载荷;没有时为 null。 |
dir、lang |
string | 文字方向("auto"、"ltr"、"rtl")与 BCP 47 语言标签。 |
requireInteraction、renotify、silent |
boolean(silent 可为 null) |
行为标志;各引擎支持情况见 Notifications API 的参数表。 |
timestamp |
number | 通知所关联的时间,自纪元起的毫秒数;默认为创建时间。 |
vibrate |
数字数组 | 振动模式,Android 上的 Chromium。 |
actions |
array | 非持久通知上恒为空数组;Service Worker 内的 event.notification 上有内容。 |
navigate |
string | 激活时打开的 URL,Safari 18.4。 |
事件有 show(已显示;iOS 上的 Safari 不触发)、click、close 与 error(显示失败,例如权限在检查与调用之间被撤销)。静态的 Notification.permission 见 Notification.requestPermission();Notification.maxActions 返回引擎会显示的操作按钮数量,在 Chromium 中为 2(notification.mojom 中的 kMaximumActions,chromium.googlesource.com),在 Safari 中为 undefined,因为该静态成员不存在。
| 异常 | 触发条件 |
|---|---|
TypeError |
在 Service Worker 内调用构造函数。Chromium 的报错文本为 Illegal constructor. Use ServiceWorkerRegistration.showNotification() instead.(notification.cc,chromium.googlesource.com)。 |
TypeError |
在 Chrome for Android 或 Samsung Internet 中从任何上下文调用构造函数;BCD 记录该构造函数在那里总是抛出(api.Notification.Notification,chrome_android)。报错文本就是同一句 Illegal constructor。 |
TypeError |
options.actions 非空。Chromium 的报错文本为 Actions are only supported for persistent notifications shown using ServiceWorkerRegistration.showNotification().。 |
TypeError |
renotify 为 true 但 tag 为空,或 silent 为 true 同时设置了 vibrate。 |
ReferenceError |
iOS 与 iPadOS 上 Safari 的浏览器标签页:除非页面是 manifest 带非默认 display 的主屏幕 Web App,否则 Notification 标识符不存在。 |
权限被拒或未决定不是异常。构造函数返回一个 Notification,其 error 事件触发而什么都不显示,这就是调用前要检查 Notification.permission 的原因。
该接口在桌面端普遍存在,在移动端要么缺失、要么没有可用的构造函数:Chrome for Android 42 与 Samsung Internet 4 只为 Service Worker 用途暴露它,iOS 上的 Safari 16.4 只在已安装的 Web App 内暴露它,Android WebView 没有(BCD api.Notification)。Chrome 自 49 起不在无痕模式显示通知。接口存在的地方实例成员和事件都受支持,但 iOS 上没有 show,而 actions、badge、image、renotify、timestamp 与 vibrate 仅限 Chromium。
第一个示例天然只适用于桌面;第二和第三个是在 Android 和 iOS 上同样可用的形态。
在桌面端显示非持久通知
Section titled “在桌面端显示非持久通知”权限已授予时,构造函数立即显示。click 处理函数聚焦窗口并关闭通知;不调用 close() 的话,操作系统会保留它直到自己的超时。
function showOrderUpdate(orderId) { const notification = new Notification('订单已发货', { body: `订单 #${orderId} 正在路上。`, icon: '/icons/parcel.png', tag: `order-${orderId}`, data: { orderId }, }); notification.addEventListener('click', () => { window.focus(); location.hash = `#order-${notification.data.orderId}`; notification.close(); }); notification.addEventListener('error', () => console.warn('通知未显示'));}浏览器在显示几秒后自行关闭非持久通知,并把它排除在通知中心之外,所以这种形态适合「已保存」之类的确认,而不适合用户会回头查看的消息。
在 Service Worker 中读取持久通知
Section titled “在 Service Worker 中读取持久通知”在 notificationclick 处理函数里,同一个接口以 event.notification 到达,此时 actions 有内容且 close() 可用。
self.addEventListener('notificationclick', (event) => { const { tag, data, actions } = event.notification; event.notification.close(); if (event.action === 'archive') { event.waitUntil(fetch(`/api/threads/${data.threadId}/archive`, { method: 'POST' })); return; } event.waitUntil(self.clients.openWindow(`/inbox#${tag}`));});这里的 actions.length 至多为 Notification.maxActions;超出该上限的按钮在显示通知时已被静默丢弃。
检测构造函数是否可用
Section titled “检测构造函数是否可用”可靠的探测是在确认接口与权限之后,在 try 里构造。任何失败都转到持久路径,而它在 Android 和 iOS 上也是唯一的路径。
async function show(title, options) { if (!('Notification' in window) || Notification.permission !== 'granted') { return showInPage(title, options.body); // 没有接口,或没有权限 } try { return new Notification(title, options); } catch (err) { if (err.name !== 'TypeError') throw err; const registration = await navigator.serviceWorker.getRegistration(); if (!registration?.active) return showInPage(title, options.body); // 没有可退回的对象 return registration.showNotification(title, options); }}生产代码通常完全跳过构造函数,在桌面和移动端都调用 showNotification();这个探测在没有注册 Service Worker 的场合才有用。
- Notifications API Standard: Notification interface(whatwg.org)
- Notification: Notification() constructor(developer.mozilla.org)
- Notifications API
- Notification.requestPermission()
- 通知的 actions 与 badge 选项
规范
| 规范 | 状态 |
|---|---|
| 无。 | |