Material: dialog: cancel errors with "Possibly unhandled rejection" when no catch exists

Created on 5 Feb 2017  路  7Comments  路  Source: angular/material

Actual Behavior:

  • What is the issue? * When calling $mdDialog.show() and the user press cancel, a message is shown in the console: "Possibly unhandled rejection: undefined"
  • What is the expected behavior?
    Recently Angular has started to log possibly unhandled rejections commit
    This is a discussion of how to handle the console errors.

    1. Give a reason in the reject (Possibly unhandled rejection: User pressed cancel)

    2. Do not use reject as a way of dismissing the dialog. According to MDN rejected promises are "almost" the same as throwing an error. This implies that a user clicking cancel is "almost" the same as handling them by throwing an exception.

    3. Add a global unhandled rejection event handler to silence all errors (including actual errors):

app.config(['$qProvider', function ($qProvider) {
$qProvider.errorOnUnhandledRejections(false);
}]);
  1. Add a catch block to the promise
$mdDialog.show({...})
    .then(confirmUserAction)
    .catch(() => {}); // or angular.noop

What are your thoughts?
Thanks

CodePen (or steps to reproduce the issue): *

  • Details:
    Create a dialog with the $mdDialog.show(). Then press the cancel button on the dialog.

Angular Versions: *

  • Angular Version: 1.6.1
  • Angular Material Version: 1.1.1

Additional Information:

  • Browser Type: * Chrome
  • Browser Version: * 55
  • OS: * MacOS
  • Stack Traces:
nice to have demo works as expected

Most helpful comment

I think ultimately Solution 2 will be the best way to handle this. I'll be using Solution 4 until we have an answer from the Angular Material team as to weather or not they want to do something like Solution 2. Thanks for posting this by the way!

All 7 comments

I think ultimately Solution 2 will be the best way to handle this. I'll be using Solution 4 until we have an answer from the Angular Material team as to weather or not they want to do something like Solution 2. Thanks for posting this by the way!

I agree that Solution 2 is probably the best way to handle this long term. Another option in the interim is something between 3 and 4-- monkey-patch the show() method in a run block rather than changing the global $qProvider or modifying every single use of $mdDialog.show().

Like:

app.run(['$mdDialog', ($mdDialog) => {
  let original = $mdDialog.show;
  $mdDialog.show = (...args) => original(...args).catch(() => {}); // or angular.noop
}]);

I haven't tested this fully. Obviously not ideal.

@keatonboyle I like your thinking. However, this causes the then(...) to always run, which, if cancel is pressed, isn't always a good idea. I've made the following modification, which throws a specific type of error. I've overridden $exceptionHandler to deal with this specific type of error:

module.run(function($mdDialog, $q){
  let original = $mdDialog.show;
  $mdDialog.show = (...args) => {
    return original(...args).catch(() => { throw 'ignore' });
  }
});

module.config(function($provide, HttpError){
  $provide.decorator('$exceptionHandler', function($delegate, $injector){
    return function(exception, cause){
      if(exception === 'Possibly unhandled rejection: ignore') return;
      $delegate(exception, cause);
    }
  });
});

+1

This is related to https://github.com/angular/material/issues/11181.

We have no plans to implement any major changes like Solution 2 would require.
Solution 4 is the recommended approach (along with possibly doing something useful in the catch block).

For reference on Solution 3, you can find the docs for $qProvider.errorOnUnhandledRejections here.

In addition to solution 3, dont use noop or any complete hiding solution:

$mdDialog.show({...})
    .then(confirmUserAction)
    .catch(function (err) {
        if (err) {
             console.error(err);
        }
    }); 

I believe that the confusion here has been settled and the approaches above are sufficient.

Was this page helpful?
0 / 5 - 0 ratings