Trước tiên, tôi xin lỗi vì tiêu đề tệ hại đó, nhưng tôi không thể không đặt.
Trong Chrome 44, Notfication.data và ServiceWorkerRegistration.getNotifications() được thêm và mở / đơn giản hoá một số trường hợp sử dụng phổ biến khi xử lý thông báo có thông báo đẩy.
Dữ liệu thông báo
Notification.data cho phép bạn liên kết một đối tượng JavaScript với một Thông báo.
Về cơ bản, điều này có nghĩa là khi nhận được thông báo đẩy, bạn có thể tạo một thông báo có một số dữ liệu, sau đó trong sự kiện notificationclick, bạn có thể nhận được thông báo đã được nhấp và nhận dữ liệu của thông báo đó.
Ví dụ: tạo một đối tượng dữ liệu và thêm đối tượng đó vào các tuỳ chọn thông báo như sau:
self.addEventListener('push', function(event) {
console.log('Received a push message', event);
var title = 'Yay a message.';
var body = 'We have received a push message.';
var icon = '/images/icon-192x192.png';
var tag = 'simple-push-demo-notification-tag';
var data = {
doge: {
wow: 'such amaze notification data'
}
};
event.waitUntil(
self.registration.showNotification(title, {
body: body,
icon: icon,
tag: tag,
data: data
})
);
});
Nghĩa là chúng ta có thể nhận thông tin trong sự kiện notificationclick:
self.addEventListener('notificationclick', function(event) {
var doge = event.notification.data.doge;
console.log(doge.wow);
});
Trước đây, bạn phải lưu trữ dữ liệu trong IndexDB hoặc đặt một nội dung nào đó vào cuối URL của biểu tượng.
ServiceWorkerRegistration.getNotifications()
Một yêu cầu phổ biến của các nhà phát triển làm việc trên thông báo đẩy là có quyền kiểm soát tốt hơn đối với thông báo mà họ hiển thị.
Một ví dụ về trường hợp sử dụng là ứng dụng nhắn tin, trong đó người dùng gửi nhiều tin nhắn và người nhận hiển thị nhiều thông báo. Lý tưởng nhất là ứng dụng web sẽ có thể nhận thấy bạn có một số thông báo chưa được xem và thu gọn các thông báo đó thành một thông báo duy nhất.
Nếu không có getNotifications(), tốt nhất bạn nên thay thế thông báo trước đó bằng thông báo mới nhất. Với getNotifications(), bạn có thể "thu gọn" thông báo nếu thông báo đã hiển thị, nhờ đó mang lại trải nghiệm tốt hơn nhiều cho người dùng.
Mã để thực hiện việc này tương đối đơn giản. Bên trong sự kiện đẩy, hãy gọi ServiceWorkerRegistration.getNotifications() để nhận một mảng Thông báo hiện tại và từ đó quyết định hành vi phù hợp, cho dù đó là thu gọn tất cả thông báo hay sử dụng thẻ Notification.
function showNotification(title, body, icon, data) {
var notificationOptions = {
body: body,
icon: icon ? icon : 'images/touch/chrome-touch-icon-192x192.png',
tag: 'simple-push-demo-notification',
data: data
};
self.registration.showNotification(title, notificationOptions);
return;
}
self.addEventListener('push', function(event) {
console.log('Received a push message', event);
// Since this is no payload data with the first version
// of Push notifications, here we'll grab some data from
// an API and use it to populate a notification
event.waitUntil(
fetch(API_ENDPOINT).then(function(response) {
if (response.status !== 200) {
console.log('Looks like there was a problem. Status Code: ' +
response.status);
// Throw an error so the promise is rejected and catch() is executed
throw new Error();
}
// Examine the text in the response
return response.json().then(function(data) {
var title = 'You have a new message';
var message = data.message;
var icon = 'images/notification-icon.png';
var notificationTag = 'chat-message';
var notificationFilter = {
tag: notificationTag
};
return self.registration.getNotifications(notificationFilter)
.then(function(notifications) {
if (notifications && notifications.length > 0) {
// Start with one to account for the new notification
// we are adding
var notificationCount = 1;
for (var i = 0; i < notifications.length; i++) {
var existingNotification = notifications[i];
if (existingNotification.data &&
existingNotification.data.notificationCount) {
notificationCount +=
existingNotification.data.notificationCount;
} else {
notificationCount++;
}
existingNotification.close();
}
message = 'You have ' + notificationCount +
' weather updates.';
notificationData.notificationCount = notificationCount;
}
return showNotification(title, message, icon, notificationData);
});
});
}).catch(function(err) {
console.error('Unable to retrieve data', err);
var title = 'An error occurred';
var message = 'We were unable to get the information for this ' +
'push message';
return showNotification(title, message);
})
);
});
self.addEventListener('notificationclick', function(event) {
console.log('On notification click: ', event);
if (Notification.prototype.hasOwnProperty('data')) {
console.log('Using Data');
var url = event.notification.data.url;
event.waitUntil(clients.openWindow(url));
} else {
event.waitUntil(getIdb().get(KEY_VALUE_STORE_NAME,
event.notification.tag).then(function(url) {
// At the moment you cannot open third party URL's, a simple trick
// is to redirect to the desired URL from a URL on your domain
var redirectUrl = '/redirect.html?redirect=' +
url;
return clients.openWindow(redirectUrl);
}));
}
});
Điều đầu tiên cần làm nổi bật với đoạn mã này là chúng ta lọc thông báo bằng cách truyền một đối tượng bộ lọc đến getNotifications(). Điều này có nghĩa là chúng ta có thể nhận được danh sách thông báo cho một thẻ cụ thể (trong ví dụ này là cho một cuộc trò chuyện cụ thể).
var notificationFilter = {
tag: notificationTag
};
return self.registration.getNotifications(notificationFilter)
Sau đó, chúng ta xem xét các thông báo hiển thị và kiểm tra xem có số lượng thông báo nào được liên kết với thông báo đó hay không và tăng số lượng dựa trên số lượng đó. Bằng cách này, nếu có một thông báo cho người dùng biết có hai tin nhắn chưa đọc, thì chúng ta sẽ muốn chỉ ra rằng có ba tin nhắn chưa đọc khi một thông báo đẩy mới đến.
var notificationCount = 1;
for (var i = 0; i < notifications.length; i++) {
var existingNotification = notifications[i];
if (existingNotification.data && existingNotification.data.notificationCount) {
notificationCount += existingNotification.data.notificationCount;
} else {
notificationCount++;
}
existingNotification.close();
}
Một điểm cần lưu ý là bạn cần gọi close()
trên thông báo để đảm bảo thông báo đó bị xoá khỏi danh sách thông báo. Đây là lỗi trong Chrome vì mỗi thông báo được thay thế bằng thông báo tiếp theo do sử dụng cùng một thẻ. Hiện tại, sự thay thế này không được phản ánh trong mảng trả về từ getNotifications()
.
Đây chỉ là một ví dụ về getNotifications() và như bạn có thể hình dung, API này mở ra một loạt các trường hợp sử dụng khác.
NotificationOptions.vibrate
Kể từ Chrome 45, bạn có thể chỉ định một kiểu rung khi tạo thông báo. Trên các thiết bị hỗ trợ API rung (hiện chỉ có Chrome dành cho Android), chế độ này cho phép bạn tuỳ chỉnh mẫu rung sẽ được sử dụng khi thông báo hiển thị.
Một mẫu rung có thể là một mảng số hoặc một số duy nhất được coi là một mảng gồm một số. Các giá trị trong mảng biểu thị thời gian tính bằng mili giây, trong đó các chỉ mục chẵn (0, 2, 4, ...) là thời lượng rung và các chỉ mục lẻ là thời lượng tạm dừng trước khi rung tiếp theo.
self.registration.showNotification('Buzz!', {
body: 'Bzzz bzzzz',
vibrate: [300, 100, 400] // Vibrate 300ms, pause 100ms, then vibrate 400ms
});
Các yêu cầu phổ biến còn lại về tính năng
Một yêu cầu phổ biến còn lại của nhà phát triển về tính năng là khả năng đóng thông báo sau một khoảng thời gian nhất định hoặc khả năng gửi thông báo đẩy với mục đích chỉ đóng thông báo nếu thông báo đó hiển thị.
Hiện tại, bạn không thể thực hiện việc này và không có gì trong thông số kỹ thuật cho phép việc này :( nhưng nhóm kỹ sư của Chrome đã biết về trường hợp sử dụng này.
Thông báo trên Android
Trên máy tính, bạn có thể tạo thông báo bằng mã sau:
new Notification('Hello', {body: 'Yay!'});
Tính năng này chưa từng được hỗ trợ trên Android do các hạn chế của nền tảng: cụ thể, Chrome không thể hỗ trợ các lệnh gọi lại trên đối tượng Notification, chẳng hạn như nhấp. Tuy nhiên, trên máy tính, thông báo này được dùng để hiển thị thông báo cho các ứng dụng web mà bạn có thể đang mở.
Lý do duy nhất tôi đề cập đến điều này là ban đầu, tính năng phát hiện tính năng đơn giản như dưới đây sẽ giúp bạn hỗ trợ máy tính và không gây ra lỗi nào trên Android:
if (!'Notification' in window) {
// Notifications aren't supported
return;
}
Tuy nhiên, với tính năng hỗ trợ thông báo đẩy hiện có trên Chrome dành cho Android, bạn có thể tạo thông báo từ ServiceWorker nhưng không thể tạo từ trang web, nghĩa là tính năng phát hiện tính năng này không còn phù hợp nữa. Nếu cố gắng tạo thông báo trên Chrome cho Android, bạn sẽ nhận được thông báo lỗi này:
_Uncaught TypeError: Failed to construct 'Notification': Illegal constructor.
Use ServiceWorkerRegistration.showNotification() instead_
Cách tốt nhất để phát hiện tính năng cho Android và máy tính tại thời điểm này là làm như sau:
function isNewNotificationSupported() {
if (!window.Notification || !Notification.requestPermission)
return false;
if (Notification.permission == 'granted')
throw new Error('You must only call this \*before\* calling
Notification.requestPermission(), otherwise this feature detect would bug the
user with an actual notification!');
try {
new Notification('');
} catch (e) {
if (e.name == 'TypeError')
return false;
}
return true;
}
Bạn có thể sử dụng như sau:
if (window.Notification && Notification.permission == 'granted') {
// We would only have prompted the user for permission if new
// Notification was supported (see below), so assume it is supported.
doStuffThatUsesNewNotification();
} else if (isNewNotificationSupported()) {
// new Notification is supported, so prompt the user for permission.
showOptInUIForNotifications();
}