Web应用想要实现类似原生应用的消息提醒能力,离不开HTML5提供的Notification API。但很多开发者在实际调用时发现,通知要么不弹出,要么直接报错,根本原因往往出在权限识别这一环节没有做好。浏览器对网页通知有严格的授权控制,只有先正确识别当前权限状态,再选择合适的时机发起请求,通知功能才能稳定运行。本文将从权限识别、授权请求、通知创建和兼容性处理几个方面,完整讲解Notification API的使用方法。

一、通知权限的三种状态与识别方法
浏览器将通知权限划分为三种状态,分别通过Notification.permission属性返回。第一种是granted,表示用户已经授权,此时可以直接创建通知;第二种是denied,表示用户明确拒绝过,任何通知调用都会被静默忽略;第三种是default,表示用户尚未做出选择,此时可以调用授权接口向用户弹出询问框。识别这三种状态是所有通知逻辑的起点。
读取权限状态的代码非常简单,直接访问静态属性即可:
// 检测浏览器是否支持 Notification API
if ('Notification' in window) {
// 获取当前权限状态
console.log('当前通知权限:', Notification.permission);
// 可能的输出:granted / denied / default
} else {
console.log('当前浏览器不支持通知功能');
}需要注意一个常见的坑:denied状态下调用授权请求不会再弹出询问框,浏览器会直接返回拒绝结果。因此实际开发中应该先判断状态,再决定是否请求授权,避免把逻辑写死。另外,部分浏览器的设置页面中用户可以随时撤回授权,所以每次页面加载时都重新读取一次权限状态是比较稳妥的做法,不要把状态缓存到localStorage里长期使用。
二、如何发起授权请求并处理回调
当权限处于default状态时,可以调用Notification.requestPermission()向用户发起授权询问。这个方法在新版标准中返回一个Promise,旧版则采用回调函数的形式,为了兼容两种写法,建议采用Promise加回调兜底的混合方式。
下面是一段兼容性较好的授权请求代码:
// 发起通知权限请求
function requestNotifyPermission() {
if (!('Notification' in window)) {
alert('当前浏览器不支持通知');
return;
}
// 优先使用 Promise 形式
if (Notification.requestPermission) {
Notification.requestPermission().then(function (result) {
handlePermissionResult(result);
});
}
}
function handlePermissionResult(result) {
if (result === 'granted') {
console.log('用户已授权,可以发送通知');
new Notification('授权成功', {
body: '感谢开启通知,后续消息会及时提醒您'
});
} else if (result === 'denied') {
console.log('用户已拒绝,需引导用户手动开启');
} else {
console.log('用户关闭了询问框,权限仍为 default');
}
}授权请求有一个非常重要的体验原则:必须在用户主动交互的上下文中触发,比如点击某个按钮之后再调用。如果在页面一加载就自动弹出授权询问,不仅用户体验差,部分浏览器(尤其是Safari和移动端Chrome)还会直接屏蔽弹窗。推荐的做法是在页面上放一个开启提醒的按钮,引导用户主动点击后再请求权限,通过率会明显提高。
如果用户曾经拒绝了授权,状态会一直停留在denied,代码层面无法再次弹出询问框。此时唯一的选择是提示用户进入浏览器站点设置手动开启通知权限,可以在页面上给出图形化的引导说明,告诉用户点击地址栏左侧的小锁图标,找到通知选项后切换为允许。
三、创建并展示一条系统通知
拿到granted授权之后,创建通知就非常直接了。通过new Notification(title, options)构造函数即可唤起一条系统级通知,第一个参数是标题,第二个参数是配置对象,支持正文、图标、标签、静音等丰富选项。
// 创建一条带图标和正文的通知
function showNotification(title, body) {
if (Notification.permission !== 'granted') {
console.warn('没有通知权限,无法发送');
return;
}
var notification = new Notification(title, {
body: body, // 通知正文
icon: 'https://ipipp.com/icon.png', // 通知图标
tag: 'order-notice', // 相同 tag 会覆盖旧通知
requireInteraction: true // 通知不自动消失(部分浏览器支持)
});
// 点击通知时聚焦到页面
notification.onclick = function () {
window.focus();
this.close();
};
// 通知被关闭时的回调
notification.onclose = function () {
console.log('通知已关闭');
};
}
showNotification('新订单提醒', '您有一笔新订单待处理,点击查看详情');tag参数很实用,相同tag的新通知会替换旧通知而不是堆叠,适合消息频繁刷新的场景。requireInteraction可以让通知保持显示直到用户操作,但移动端浏览器大多不支持。此外,部分浏览器要求页面必须使用HTTPS协议,否则Notification API会直接不可用,本地开发时可以用localhost,它被视为安全上下文。
服务Worker环境下还有registration.showNotification()这种替代写法,它配合Service Worker可以在页面关闭后仍然展示通知,适合做后台推送。普通网页内通知则用构造函数方式即可,两者参数基本一致,按场景选择即可。
四、常见问题与降级方案
实际调试中,通知不弹出通常有这几类原因:页面非HTTPS环境、权限是denied、浏览器系统层面关闭了网站通知总开关、或者移动端浏览器根本不支持网页通知。排查时可以按照代码检测、浏览器站点设置、操作系统通知设置三个层级依次检查。
对于不支持或未授权的环境,应该提供优雅的降级方案,比如改用页面内的浮层提醒、标题栏闪烁提示,或者在用户下次访问时展示站内消息中心。下面是一个完整的封装函数,把权限检测、请求和发送整合在一起:
// 通知功能完整封装
var Notify = {
// 检查是否可用
isSupported: function () {
return 'Notification' in window;
},
// 确保已授权,返回 Promise
ensurePermission: function () {
if (Notification.permission === 'granted') {
return Promise.resolve('granted');
}
if (Notification.permission === 'denied') {
return Promise.reject(new Error('权限已被拒绝,请手动开启'));
}
return Notification.requestPermission();
},
// 发送通知,失败时降级为控制台提示
send: function (title, options) {
var self = this;
if (!this.isSupported()) {
console.warn('浏览器不支持通知,降级为页面提醒');
return false;
}
this.ensurePermission().then(function (result) {
if (result === 'granted') {
new Notification(title, options || {});
}
}).catch(function (err) {
console.warn(err.message);
});
return true;
}
};
// 使用示例:在按钮点击事件中调用
document.getElementById('notifyBtn').addEventListener('click', function () {
Notify.send('库存预警', { body: '商品库存不足,请及时补货' });
});总结一下,HTML5通知功能的正确实现路径是:先检测支持性,再读取权限状态,然后等待用户交互时请求授权,最后才创建通知。把这四步的顺序理清楚,通知相关的绝大多数问题都能迎刃而解。建议在正式项目中始终封装一层类似上面的工具函数,把权限判断和降级逻辑收口到一处,后续维护会轻松很多。
HTML5通知权限Notification APIWeb通知修改时间:2026-09-01 12:03:00