【问题标题】:Error getting PushManager Subscription - JavaScript获取 PushManager 订阅时出错 - JavaScript
【发布时间】:2018-12-17 14:58:52
【问题描述】:

我有以下代码注册服务工作者并要求用户允许通知。在用户允许serviceWorkerRegistration.pushManager.getSubscription() 返回的承诺为null 的推送通知后,我收到错误消息。当我关闭浏览器并再次强制调用此函数时,它可以正常工作。我不明白为什么。这是我的代码:

window.vapidPublicKey = new Uint8Array([4, 45, ...]); 
if (navigator.serviceWorker) {
  navigator.serviceWorker.register('/serviceworker.js')
  .then(function(reg) {
     console.log('Service worker change, registered the service worker');
  });
}
// Otherwise, no push notifications :(
else {
  console.error('Service worker is not supported in this browser');
}

navigator.serviceWorker.ready.then((serviceWorkerRegistration) => {
  console.log("ready");
  serviceWorkerRegistration.pushManager
  .subscribe({
    userVisibleOnly: true,
    applicationServerKey: window.vapidPublicKey
  });
});



// application.js

// Let's check if the browser supports notifications
if (!("Notification" in window)) {
  console.error("This browser does not support notifications.");
}

// Let's check whether notification permissions have already been granted
else if (Notification.permission === "granted") {
  console.log("Permission to receive notifications has been granted");
}

// Otherwise, we need to ask the user for permission
else if (Notification.permission !== 'denied') {
  Notification.requestPermission(function (permission) {
    // If the user accepts, let's create a notification
    if (permission === "granted") {
      console.log("Permission to receive notifications has been granted");
      saveSubscriptionToDatabase();
    }
  });
}

function saveSubscriptionToDatabase(){

      navigator.serviceWorker.ready
      .then((serviceWorkerRegistration) => {
        console.log(serviceWorkerRegistration.pushManager.getSubscription());
        serviceWorkerRegistration.pushManager.getSubscription()
        .then((subscription) => {
          $.post("/users/save_subscription", { subscription: subscription.toJSON() });
        });
      });

}

错误:

Uncaught (in promise) TypeError: Cannot read property 'toJSON' of null
at serviceWorkerRegistration.pushManager.getSubscription.then

更新:

所以我添加了以下按钮:

 <input type="button" onclick="saveSubscriptionToDatabase();" value="test">

只要我从按钮单击调用该函数,所有 JS 和发布请求都按预期工作,但是当我从检查权限状态的条件调用它时,它仍然像以前一样失败。

更新 2:

我已经尝试再次编写代码,但从不同的角度。

function registerServiceWorker() {
  return navigator.serviceWorker.register('serviceworker.js')
  .then(function(registration) {
    console.log('Service worker successfully registered.');
    return registration;
  })
  .catch(function(err) {
    console.error('Unable to register service worker.', err);
  });
}


function askPermission() {
  return new Promise(function(resolve, reject) {
    const permissionResult = Notification.requestPermission(function(result) {
      resolve(result);
    });

    if (permissionResult) {
      permissionResult.then(resolve, reject);
    }
  })
  .then(function(permissionResult) {
    if (permissionResult !== 'granted') {
      throw new Error('We weren\'t granted permission.');
    }
  });
}


function subscribeUserToPush() {
  return navigator.serviceWorker.register('serviceworker.js')
  .then(function(registration) {
    const subscribeOptions = {
      userVisibleOnly: true,
      applicationServerKey: new Uint8Array("key goes here")

    };

    return registration.pushManager.subscribe(subscribeOptions);
  })
  .then(function(pushSubscription) {
    console.log("never called");
    console.log('Received PushSubscription: ', JSON.stringify(pushSubscription));
    return pushSubscription;
  });
}

registerServiceWorker();
askPermission();
subscribeUserToPush();

subscribeUserToPush() 中我拥有console.log("never called"); 的命令链的最后一部分永远不会执行并且没有错误。我正在 Chrome 67 中对此进行测试。我很肯定 registration.pushManager.subscribe(subscribeOptions); 被调用了。

【问题讨论】:

  • 可能你在这里拼错了,但在其他地方使用正确的拼写:vapidPublicKey
  • 要尝试的另一件事是创建一个带有按钮的页面,单击该按钮将发送您的 $.post 请求。然后使用 fiddler 等工具进行故障排除,以获取响应/请求标头、参数或任何其他错误..

标签: javascript push-notification web-push


【解决方案1】:

因此,经过数小时尝试不同的事情后,我终于找出了问题所在,而且非常简单。所以每次调用navigator.serviceWorker.register('serviceworker.js') 时都必须在文件名前加上/。如果没有/,服务人员将可以正常注册,但获取订阅将失败。您在文档中找到的示例不包括 /

所以,代码应该是这样的:

navigator.serviceWorker.register('/serviceworker.js')

Tada 现在可以了....

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-06-29
    • 2017-03-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-05
    • 1970-01-01
    • 2020-01-06
    相关资源
    最近更新 更多