Web-Push 通知脚本适用于 Firefox 但不适用于 Chrome
Web-Push notification script working on Firefox but not on Chrome
我正在构建一个网络推送通知系统,我正在使用本示例中使用的概念:
https://github.com/Minishlink/web-push-php-example
我的 JS 文件中有以下代码。它检查 API 支持,检查通知是否未禁用,注册服务工作者,请求显示通知的权限,如果允许则订阅用户并将详细信息发送到服务器。如果用户已经订阅,它会更新数据库中的端点值。
当我在 Firefox 61 上 运行 它工作正常,但是当我在 Chrome 67 上 运行 它时,我得到这个错误:
Uncaught (in promise) TypeError: Cannot read property 'getKey' of null
at pushSubscribe (notification.js:48)
at navigator.serviceWorker.ready.then.then.subscription (notification.js:30)
我的理解是 Chrome 在服务工作人员注册和用户订阅时没有检测到 订阅,因此它给出了错误。有什么解决办法吗?
谢谢。
document.addEventListener('DOMContentLoaded', () => {
// Feature detection
if (!('serviceWorker' in navigator)) {
alert('Service Worker API isn’t supported.');
} else if (!('PushManager' in window)) {
alert('Push API isn’t supported.');
} else if (!('Notification' in window)) {
alert('Notifications API isn’t supported.');
} else if (!('showNotification' in ServiceWorkerRegistration.prototype)) {
alert('Notifications aren’t supported.');
// Check permission
} else if (Notification.permission == 'denied') {
alert('Notifications are disabled.');
} else {
// Register service worker
navigator.serviceWorker.register('/service-worker.js').then(() => {
navigator.serviceWorker.ready.then(serviceWorkerRegistration => serviceWorkerRegistration.pushManager.getSubscription()).then(subscription => {
if (!subscription) {
// Subscribe user
navigator.serviceWorker.ready.then(serviceWorkerRegistration => serviceWorkerRegistration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: urlBase64ToUint8Array('BNwjaNBKGM13IAef-gJr7C95W3yLJe2F5X0zLnwacN3zCnZK15Vqf3ijeHl9k7K0yBFX3ZwxAmldPoVDpi6iETA'),
})).then(subscription => {
return pushSubscribe(subscription);
});
}
// Update endpoint
return pushSubscribe(subscription);
});
});
function urlBase64ToUint8Array(base64String) {
const padding = '='.repeat((4 - base64String.length % 4) % 4);
const base64 = (base64String + padding).replace(/\-/g, '+').replace(/_/g, '/');
const rawData = window.atob(base64);
const outputArray = new Uint8Array(rawData.length);
for (let i = 0; i < rawData.length; ++i) {
outputArray[i] = rawData.charCodeAt(i);
}
return outputArray;
}
function pushSubscribe(subscription) {
const key = subscription.getKey('p256dh');
const token = subscription.getKey('auth');
const contentEncoding = (PushManager.supportedContentEncodings || ['aesgcm'])[0];
return fetch('/scripts/notification-subscribe.php', {
method: 'POST',
body: JSON.stringify({
endpoint: subscription.endpoint,
publicKey: key ? btoa(String.fromCharCode.apply(null, new Uint8Array(key))) : null,
authToken: token ? btoa(String.fromCharCode.apply(null, new Uint8Array(token))) : null,
contentEncoding,
user: userId, // generated beforehand
}),
}).then(() => subscription);
}
}
});
if(subscription){
const key = subscription.getKey('p256dh');
const token = subscription.getKey('auth');
const contentEncoding = (PushManager.supportedContentEncodings || ['aesgcm'])[0];
return fetch('/scripts/notification-subscribe.php', {
method: 'POST',
body: JSON.stringify({
endpoint: subscription.endpoint,
publicKey: key ? btoa(String.fromCharCode.apply(null, new Uint8Array(key))) : null,
authToken: token ? btoa(String.fromCharCode.apply(null, new Uint8Array(token))) : null,
contentEncoding,
user: 1,
}),
}).then(() => subscription);
}
}
Just modify this function hope pushSubscription with if block it works
我正在构建一个网络推送通知系统,我正在使用本示例中使用的概念:
https://github.com/Minishlink/web-push-php-example
我的 JS 文件中有以下代码。它检查 API 支持,检查通知是否未禁用,注册服务工作者,请求显示通知的权限,如果允许则订阅用户并将详细信息发送到服务器。如果用户已经订阅,它会更新数据库中的端点值。
当我在 Firefox 61 上 运行 它工作正常,但是当我在 Chrome 67 上 运行 它时,我得到这个错误:
Uncaught (in promise) TypeError: Cannot read property 'getKey' of null
at pushSubscribe (notification.js:48)
at navigator.serviceWorker.ready.then.then.subscription (notification.js:30)
我的理解是 Chrome 在服务工作人员注册和用户订阅时没有检测到 订阅,因此它给出了错误。有什么解决办法吗?
谢谢。
document.addEventListener('DOMContentLoaded', () => {
// Feature detection
if (!('serviceWorker' in navigator)) {
alert('Service Worker API isn’t supported.');
} else if (!('PushManager' in window)) {
alert('Push API isn’t supported.');
} else if (!('Notification' in window)) {
alert('Notifications API isn’t supported.');
} else if (!('showNotification' in ServiceWorkerRegistration.prototype)) {
alert('Notifications aren’t supported.');
// Check permission
} else if (Notification.permission == 'denied') {
alert('Notifications are disabled.');
} else {
// Register service worker
navigator.serviceWorker.register('/service-worker.js').then(() => {
navigator.serviceWorker.ready.then(serviceWorkerRegistration => serviceWorkerRegistration.pushManager.getSubscription()).then(subscription => {
if (!subscription) {
// Subscribe user
navigator.serviceWorker.ready.then(serviceWorkerRegistration => serviceWorkerRegistration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: urlBase64ToUint8Array('BNwjaNBKGM13IAef-gJr7C95W3yLJe2F5X0zLnwacN3zCnZK15Vqf3ijeHl9k7K0yBFX3ZwxAmldPoVDpi6iETA'),
})).then(subscription => {
return pushSubscribe(subscription);
});
}
// Update endpoint
return pushSubscribe(subscription);
});
});
function urlBase64ToUint8Array(base64String) {
const padding = '='.repeat((4 - base64String.length % 4) % 4);
const base64 = (base64String + padding).replace(/\-/g, '+').replace(/_/g, '/');
const rawData = window.atob(base64);
const outputArray = new Uint8Array(rawData.length);
for (let i = 0; i < rawData.length; ++i) {
outputArray[i] = rawData.charCodeAt(i);
}
return outputArray;
}
function pushSubscribe(subscription) {
const key = subscription.getKey('p256dh');
const token = subscription.getKey('auth');
const contentEncoding = (PushManager.supportedContentEncodings || ['aesgcm'])[0];
return fetch('/scripts/notification-subscribe.php', {
method: 'POST',
body: JSON.stringify({
endpoint: subscription.endpoint,
publicKey: key ? btoa(String.fromCharCode.apply(null, new Uint8Array(key))) : null,
authToken: token ? btoa(String.fromCharCode.apply(null, new Uint8Array(token))) : null,
contentEncoding,
user: userId, // generated beforehand
}),
}).then(() => subscription);
}
}
});
if(subscription){
const key = subscription.getKey('p256dh');
const token = subscription.getKey('auth');
const contentEncoding = (PushManager.supportedContentEncodings || ['aesgcm'])[0];
return fetch('/scripts/notification-subscribe.php', {
method: 'POST',
body: JSON.stringify({
endpoint: subscription.endpoint,
publicKey: key ? btoa(String.fromCharCode.apply(null, new Uint8Array(key))) : null,
authToken: token ? btoa(String.fromCharCode.apply(null, new Uint8Array(token))) : null,
contentEncoding,
user: 1,
}),
}).then(() => subscription);
}
}
Just modify this function hope pushSubscription with if block it works