Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PWA beforeinstallprompt Uncaught (in promise) DOMException

The below function works fine when a user installs the pwa. If they decline however, the next time they come on to the site, deferredPrompt.prompt(); throws the Uncaught (in promise) DOMException exception, even though deferredPrompt.prompt(); is not undefined.

Is there something I need to check for regarding a users previously given answer?

window.addEventListener('beforeinstallprompt', (e) => {
    // Prevent Chrome 67 and earlier from automatically showing the prompt
    //e.preventDefault();

    let deferredPrompt;

    // Stash the event so it can be triggered later.
    deferredPrompt = e;
    // Show the prompt
    deferredPrompt.prompt();
    // Wait for the user to respond to the prompt
    deferredPrompt.userChoice
    .then((choiceResult) => {
      if (choiceResult.outcome === 'accepted') {
        console.log('User accepted the A2HS prompt');
      } else {
        console.log('User dismissed the A2HS prompt');
      }
      deferredPrompt = null;
    });
});
like image 358
rory Avatar asked May 21 '19 10:05

rory


1 Answers

I have similar code and encounter the same problem. After some researches, I understand that deferredPrompt.prompt() will return a userResponsePromise which is a promise. Then I try to see what happen by adding this line of code to observe the log.

deferredPrompt.prompt()
  .then(res => console.log(res))
  .catch(error => { console.log(`----> ${error}`) })

at the console log, it shows

----> NotAllowedError: The prompt() method must be called with a user gesture

I guess the A2HS installation process may not allow calling prompt() directly. Therefore I try to change my code to by setup a call to action button that will call prompt() method which I suppose it should imply to the meaning of 'user gesture' as the log suggest.

Here is my new code which is look like the code from Add to Home Screen tutorial from Google dev. (I don't know why I didnot follow it at the first time :P)

window.addEventListener('beforeinstallprompt', e => {
  e.preventDefault()
  deferredPrompt = e
})

const btnInstallApp = document.getElementById('btn-install-app')

if(btnInstallApp) {
  btnInstallApp.addEventListener('click', e => {
    deferredPrompt.prompt()
    deferredPrompt.userChoice
      .then(choiceResult => {
        if(choiceResult.outcome === 'accepted') {
          console.log('user accepted A2HS prompt')
        } else {
          console.log('user dismissed A2HS prompt')
        }
        deferredPrompt = null
      })
    })
}

The I add my Install App button somewhere in the page

<button id="btn-install-app" class="btn">Install App</button>

This time I can see the Add to Homescreen prompt after I click the Install App button. I hope this help.

like image 163
worrawut Avatar answered Nov 08 '22 10:11

worrawut