【发布时间】:2018-12-21 13:13:55
【问题描述】:
我正在构建一个网络推送通知系统,我正在使用本示例中使用的概念:
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);
}
}
});
【问题讨论】:
-
Chrome 控制台是否有错误
-
@SiddharthJain 是的,Chrome 控制台中显示的错误在问题中。
-
能否请您在不同级别进行调试,我认为订阅在第一次调用时会变得未定义,您能否在订阅之前测试条件。getKey
-
@SiddharthJain 抱歉,我不清楚如何进行 if 条件检查。 “//注册服务工作者”下的 IF 检查似乎在 Chrome 上也可以正常工作。
-
在 pushSubscribe 函数中
标签: javascript google-chrome push-notification web-push