安全上下文
此特征只可用于
安全上下文
(HTTPS),在某些或所有
支持浏览器
.
Notifications API lets a web page or app send notifications that are displayed outside the page at the system level; this lets web apps send information to a user even if the application is idle or in the background. This article looks at the basics of using this API in your own apps.
Typically, system notifications refer to the operating system's standard notification mechanism: think for example of how a typical desktop system or mobile device broadcasts notifications.
The system notification system will vary of course by platform and browser, but this is ok, and the Notifications API is written to be general enough for compatibility with most system notification systems.
One of the most obvious use cases for web notifications is a web-based mail or IRC application that needs to notify the user when a new message is received, even if the user is doing something else with another application. Many examples of this now exist, such as Slack .
We've written a real world example — a to-do list app — to give more of an idea of how web notifications can be used. It stores data locally using IndexedDB and notifies users when tasks are due using system notifications. Download the To-do list code ,或 view the app running live .
Before an app can send a notification, the user must grant the application the right to do so. This is a common requirement when an API tries to interact with something outside a web page — at least once, the user needs to specifically grant that application permission to present notifications, thereby letting the user control which apps/sites are allowed to display notifications.
Because of abuses of push notifications in the past, web browsers and developers have begun to implement strategies to help mitigate this problem. You should only request consent to display notifications in response to a user gesture (e.g. clicking a button). This is not only best practice — you should not be spamming users with notifications they didn't agree to — but going forward browsers will explicitly disallow notification permission requests not triggered in response to a user gesture. Firefox is already doing this from version 72, for example, and Safari has done it for some time.
In addition, In Chrome and Firefox you cannot request notifications at all unless the site is a secure context (i.e. HTTPS), and you can no longer allow notification permissions to be requested from cross-origin
<iframe>
。
You can check to see if you already have permission by checking the value of the
Notification.permission
read only property. It can have one of three possible values:
default
The user hasn't been asked for permission yet, so notifications won't be displayed.
granted
The user has granted permission to display notifications, after having been asked previously.
denied
The user has explicitly declined permission to show notifications.
If permission to display notifications hasn't been granted yet, the application needs to use the
Notification.requestPermission()
method to request this from the user. In its simplest form, we just include the following:
Notification.requestPermission().then(function(result) {
console.log(result);
});
This uses the promise-based version of the method. If you want to support older versions, you might have to use the older callback version, which looks like this:
Notification.requestPermission();
The callback version optionally accepts a callback function that is called once the user has responded to the request to display permissions.
In our todo list demo, we include an "Enable notifications" button that, when pressed, requests notification permissions for the app.
<button id="enable">Enable notifications</button>
Clicking this calls the
askNotificationPermission()
函数:
function askNotificationPermission() {
// function to actually ask the permissions
function handlePermission(permission) {
// Whatever the user answers, we make sure Chrome stores the information
if(!('permission' in Notification)) {
Notification.permission = permission;
}
// set the button to shown or hidden, depending on what the user answers
if(Notification.permission === 'denied' || Notification.permission === 'default') {
notificationBtn.style.display = 'block';
} else {
notificationBtn.style.display = 'none';
}
}
// Let's check if the browser supports notifications
if (!('Notification' in window)) {
console.log("This browser does not support notifications.");
} else {
if(checkNotificationPromise()) {
Notification.requestPermission()
.then((permission) => {
handlePermission(permission);
})
} else {
Notification.requestPermission(function(permission) {
handlePermission(permission);
});
}
}
}
Looking at the second main block first, you'll see that we first check to see if Notifications are supported. If they are, we then run a check to see whether the promise-based version of
Notification.requestPermission()
is supported. If it is, we run the promise-based version (supported everywhere except Safari), and if not, we run the older callback-based version (which is supported in Safari).
To avoid duplicating code, we have stored a few bits of housekeeping code inside the
handlePermission()
function, which is the first main block inside this snippet. Inside here we explicitly set the
Notification.permission
value (some old versions of Chrome failed to do this automatically), and show or hide the button depending on what the user chose in the permission dialog. We don't want to show it if permission has already been granted, but if the user chose to deny permission, we want to give them the chance to change their mind later on.
注意:
Before version 37, Chrome doesn't let you call
Notification.requestPermission()
在
load
event handler (see
issue 274284
).
Above we said that we had to check whether the browser supports the promise version of
Notification.requestPermission()
. We did this using the following:
function checkNotificationPromise() {
try {
Notification.requestPermission().then();
} catch(e) {
return false;
}
return true;
}
We basically try to see if the
.then()
method is available on
requestPermission()
. If so, we move on and return
true
. If it fails, we return
false
在
catch() {}
块。
Creating a notification is easy; just use the
Notification
constructor. This constructor expects a title to display within the notification and some options to enhance the notification such as an
icon
or a text
body
.
For example, in the to-do-list example we use the following snippet to create a notification when required (found inside the
createNotification()
function):
var img = '/to-do-notifications/img/icon-128.png';
var text = 'HEY! Your task "' + title + '" is now overdue.';
var notification = new Notification('To do list', { body: text, icon: img });
Used
close()
to remove a notification that is no longer relevant to the user (e.g. the user already read the notification on the webpage, in the case of a messaging app, or the following song is already playing in a music app to notifies upon song changes). Most modern browsers dismiss notifications automatically after a few moments (around four seconds) but this isn't something you should generally be concerned about as it's up to the user and user agent. The dismissal may also happen at the operating system level and users should remain in control of this. Old versions of Chrome didn't remove notifications automatically so you can do so after a
setTimeout()
only for those legacy versions in order to not remove notifications from notification trays on other browsers.
var n = new Notification('My Great Song');
document.addEventListener('visibilitychange', function() {
if (document.visibilityState === 'visible') {
// The tab has become visible so clear the now-stale Notification.
n.close();
}
});
注意: This API shouldn't be used just to have the notification removed from the screen after a fixed delay (on modern browsers) since this method will also remove the notification from any notification tray, preventing users from interacting with it after it was initially shown.
注意 : When you receive a "close" event, there is no guarantee that it's the user who closed the notification. This is in line with the specification, which states: "When a notification is closed, either by the underlying notifications platform or by the user, the close steps for it must be run."
There are four events that are triggered on the
Notification
实例:
click
Triggered when the user clicks on the notification.
close
Triggered once the notification is closed.
error
Triggered if something goes wrong with the notification; this is usually because the notification couldn't be displayed for some reason.
show
Triggered when the notification is displayed to the user.
These events can be tracked using the
onclick
,
onclose
,
onerror
,和
onshow
handlers. Because
Notification
also inherits from
EventTarget
, it's possible to use the
addEventListener()
method on it.
It is usually undesirable for a user to receive a lot of notifications in a short space of time — for example, what if a messenger application notified a user for each incoming message, and they were being sent a lot? To avoid spamming the user with too many notifications, it's possible to modify the pending notifications queue, replacing single or multiple pending notifications with a new one.
To do this, it's possible to add a tag to any new notification. If a notification already has the same tag and has not been displayed yet, the new notification replaces that previous notification. If the notification with the same tag has already been displayed, the previous notification is closed and the new one is displayed.
Assume the following basic HTML:
<button>Notify me!</button>
It's possible to handle multiple notifications this way:
window.addEventListener('load', function () {
// At first, let's check if we have permission for notification
// If not, let's ask for it
if (window.Notification && Notification.permission !== "granted") {
Notification.requestPermission(function (status) {
if (Notification.permission !== status) {
Notification.permission = status;
}
});
}
var button = document.getElementsByTagName('button')[0];
button.addEventListener('click', function () {
// If the user agreed to get notified
// Let's try to send ten notifications
if (window.Notification && Notification.permission === "granted") {
var i = 0;
// Using an interval cause some browsers (including Firefox) are blocking notifications if there are too much in a certain time.
var interval = window.setInterval(function () {
// Thanks to the tag, we should only see the "Hi! 9" notification
var n = new Notification("Hi! " + i, {tag: 'soManyNotification'});
if (i++ == 9) {
window.clearInterval(interval);
}
}, 200);
}
// If the user hasn't told if he wants to be notified or not
// Note: because of Chrome, we are not sure the permission property
// is set, therefore it's unsafe to check for the "default" value.
else if (window.Notification && Notification.permission !== "denied") {
Notification.requestPermission(function (status) {
// If the user said okay
if (status === "granted") {
var i = 0;
// Using an interval cause some browsers (including Firefox) are blocking notifications if there are too much in a certain time.
var interval = window.setInterval(function () {
// Thanks to the tag, we should only see the "Hi! 9" notification
var n = new Notification("Hi! " + i, {tag: 'soManyNotification'});
if (i++ == 9) {
window.clearInterval(interval);
}
}, 200);
}
// Otherwise, we can fallback to a regular modal alert
else {
alert("Hi!");
}
});
}
// If the user refuses to get notified
else {
// We can fallback to a regular modal alert
alert("Hi!");
}
});
});
See the live result below:
| 规范 | 状态 | 注释 |
|---|---|---|
| Notifications API | 实时标准 | Living standard |
| 桌面 | 移动 | |||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
Notification
|
Chrome
22
|
Edge 14 |
Firefox
22
|
IE No | Opera 25 | Safari 6 | WebView Android No | Chrome Android Yes |
Firefox Android
22
|
Opera Android Yes | Safari iOS No | Samsung Internet Android Yes |
Notification()
构造函数
|
Chrome
22
|
Edge ≤18 |
Firefox
22
|
IE No | Opera 25 | Safari 6 | WebView Android No | Chrome Android Yes |
Firefox Android
22
|
Opera Android Yes | Safari iOS No | Samsung Internet Android Yes |
actions
|
Chrome 53 | Edge 18 | Firefox No | IE No | Opera 39 | Safari ? | WebView Android No | Chrome Android 53 | Firefox Android No | Opera Android 41 | Safari iOS No | Samsung Internet Android 6.0 |
badge
|
Chrome 53 | Edge 18 | Firefox No | IE No | Opera 39 | Safari ? | WebView Android No | Chrome Android 53 | Firefox Android No | Opera Android 41 | Safari iOS No | Samsung Internet Android 6.0 |
body
|
Chrome Yes | Edge 14 | Firefox Yes | IE No | Opera Yes | Safari Yes | WebView Android No | Chrome Android Yes | Firefox Android Yes | Opera Android Yes | Safari iOS No | Samsung Internet Android Yes |
close
|
Chrome Yes | Edge 14 | Firefox Yes | IE No | Opera Yes | Safari Yes | WebView Android No | Chrome Android Yes | Firefox Android Yes | Opera Android Yes | Safari iOS No | Samsung Internet Android Yes |
data
|
Chrome Yes | Edge 16 | Firefox Yes | IE No | Opera Yes | Safari ? | WebView Android No | Chrome Android Yes | Firefox Android Yes | Opera Android Yes | Safari iOS No | Samsung Internet Android Yes |
dir
|
Chrome Yes | Edge 14 | Firefox Yes | IE No | Opera Yes | Safari Yes | WebView Android No | Chrome Android Yes | Firefox Android Yes | Opera Android Yes | Safari iOS No | Samsung Internet Android Yes |
icon
|
Chrome
22
|
Edge 14 |
Firefox
22
|
IE No | Opera 25 | Safari No | WebView Android No | Chrome Android Yes |
Firefox Android
22
|
Opera Android Yes | Safari iOS No | Samsung Internet Android Yes |
image
|
Chrome 53 | Edge 18 | Firefox No | IE No | Opera 40 | Safari ? | WebView Android No | Chrome Android 53 | Firefox Android No | Opera Android 41 | Safari iOS No | Samsung Internet Android 6.0 |
lang
|
Chrome Yes | Edge 14 | Firefox Yes | IE No | Opera Yes | Safari Yes | WebView Android No | Chrome Android Yes | Firefox Android Yes | Opera Android Yes | Safari iOS No | Samsung Internet Android Yes |
maxActions
|
Chrome Yes | Edge 18 | Firefox No | IE No | Opera Yes | Safari ? | WebView Android No | Chrome Android Yes | Firefox Android No | Opera Android Yes | Safari iOS No | Samsung Internet Android Yes |
onclick
|
Chrome Yes | Edge 14 | Firefox 22 | IE No | Opera Yes | Safari Yes | WebView Android No | Chrome Android Yes | Firefox Android No | Opera Android Yes | Safari iOS No | Samsung Internet Android Yes |
onclose
|
Chrome Yes | Edge 14 | Firefox Yes | IE No | Opera Yes | Safari Yes | WebView Android No | Chrome Android Yes | Firefox Android Yes | Opera Android Yes | Safari iOS No | Samsung Internet Android Yes |
onerror
|
Chrome Yes | Edge 14 | Firefox No | IE No | Opera Yes | Safari Yes | WebView Android No | Chrome Android Yes | Firefox Android No | Opera Android Yes | Safari iOS No | Samsung Internet Android Yes |
onshow
|
Chrome Yes | Edge 14 | Firefox Yes | IE No | Opera Yes | Safari Yes | WebView Android No | Chrome Android Yes | Firefox Android Yes | Opera Android Yes | Safari iOS No | Samsung Internet Android Yes |
permission
|
Chrome Yes | Edge 14 | Firefox Yes | IE No | Opera Yes | Safari Yes | WebView Android No | Chrome Android Yes | Firefox Android Yes | Opera Android Yes | Safari iOS No | Samsung Internet Android Yes |
renotify
|
Chrome 50 | Edge 79 | Firefox No | IE No | Opera 37 | Safari No | WebView Android No | Chrome Android 50 | Firefox Android No | Opera Android 37 | Safari iOS No | Samsung Internet Android 5.0 |
requestPermission
|
Chrome 46 | Edge 14 |
Firefox
47
|
IE No | Opera 40 | Safari Yes | WebView Android No | Chrome Android 46 | Firefox Android Yes | Opera Android 41 | Safari iOS No | Samsung Internet Android 5.0 |
requireInteraction
|
Chrome Yes | Edge 17 | Firefox No | IE No | Opera Yes | Safari ? | WebView Android No | Chrome Android Yes | Firefox Android No | Opera Android Yes | Safari iOS No | Samsung Internet Android Yes |
| Secure context required | Chrome 62 | Edge ≤79 | Firefox 67 | IE No | Opera 49 | Safari ? | WebView Android No | Chrome Android 62 | Firefox Android 67 | Opera Android 46 | Safari iOS No | Samsung Internet Android 8.0 |
silent
|
Chrome 43 | Edge 17 | Firefox No | IE No | Opera 30 | Safari No | WebView Android No | Chrome Android 43 | Firefox Android No | Opera Android 30 | Safari iOS No | Samsung Internet Android 4.0 |
tag
|
Chrome Yes | Edge 14 | Firefox Yes | IE No | Opera Yes | Safari Yes | WebView Android No | Chrome Android Yes | Firefox Android Yes | Opera Android Yes | Safari iOS No | Samsung Internet Android Yes |
timestamp
|
Chrome Yes | Edge 17 | Firefox No | IE No | Opera Yes | Safari ? | WebView Android No | Chrome Android Yes | Firefox Android No | Opera Android Yes | Safari iOS No | Samsung Internet Android Yes |
title
|
Chrome Yes | Edge 14 | Firefox No | IE No | Opera Yes | Safari Yes | WebView Android No | Chrome Android Yes | Firefox Android No | Opera Android Yes | Safari iOS No | Samsung Internet Android Yes |
vibrate
|
Chrome No | Edge No | Firefox No | IE No | Opera No | Safari ? | WebView Android No |
Chrome Android
53
|
Firefox Android No |
Opera Android
41
|
Safari iOS No |
Samsung Internet Android
6.0
|
| Available in workers | Chrome 45 | Edge ≤18 | Firefox 41 | IE No | Opera 32 | Safari ? | WebView Android No | Chrome Android 45 | Firefox Android 41 | Opera Android 32 | Safari iOS No | Samsung Internet Android 5.0 |
完整支持
不支持
兼容性未知
见实现注意事项。
要求使用供应商前缀或不同名称。