rory
rory

Reputation: 1438

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;
    });
});

Upvotes: 10

Views: 4926

Answers (2)

calterras
calterras

Reputation: 308

Be carefull!

My pwa code is similar and worked ok. However, suddently, after a trivial change in code, I got this error in debug mode using chrome developer tools.

I noticed that I had set a breakpoint imediately before deferredPromt.prompt(). This caused the error because the listener sets a timer in order to detect if event was due to a user gesture.

Unsetting the breakpoint my code worked again.

Upvotes: 0

worrawut
worrawut

Reputation: 1068

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.

Upvotes: 6

Related Questions