title: Error getting PushManager Subscription - JavaScript
body: <p>I've got the following code that registers a service worker and asks the user allow notifications. I'm getting an error after the user allows the push notifications where the promise returned by <code>serviceWorkerRegistration.pushManager.getSubscription()</code> is <code>null</code>. When I close the browser and force this function call again, it works without errors. I don't understand why. Here is my code:</p>
  
  <p></p>
  
  <pre><code>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) =&gt; {
    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) =&gt; {
          console.log(serviceWorkerRegistration.pushManager.getSubscription());
          serviceWorkerRegistration.pushManager.getSubscription()
          .then((subscription) =&gt; {
            $.post("/users/save_subscription", { subscription: subscription.toJSON() });
          });
        });
  
  }
  </code></pre>
  
  <p></p>
  
  <p>The error:</p>
  
  <pre><code>Uncaught (in promise) TypeError: Cannot read property 'toJSON' of null
  at serviceWorkerRegistration.pushManager.getSubscription.then
  </code></pre>
  
  <p>UPDATE:</p>
  
  <p>So I added the following button:</p>
  
  <pre><code> &lt;input type="button" onclick="saveSubscriptionToDatabase();" value="test"&gt;
  </code></pre>
  
  <p>All of the JS and post request works as expected as long as I call the function from the button click but when I call it from the conditional that checks the permission state, it still fails just like before. </p>
  
  <p>UPDATE 2:</p>
  
  <p>I've tried writing the code again but from a different angle.</p>
  
  <pre><code>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();
  </code></pre>
  
  <p>The last part of the command chain in <code>subscribeUserToPush()</code> where I have <code>console.log("never called");</code> never executes and has no errors. I'm testing this in Chrome 67. I am positive that <code>registration.pushManager.subscribe(subscribeOptions);</code> is called.</p>