How to handle 'Possibly unhandled rejection: b

2019-02-16 07:51发布

问题:

I have an angular service for handling modals:

angular.module('myApp').service('ModalService', function($uibModal) {
  function open(options) {
    return $uibModal.open(options);
  }
});

Now I upgraded to angular 1.6 and got this error:

Possibly unhandled rejection: backdrop click

whenever I open a modal and click somewhere else (the backdrop) and the modal closes (as intended). So I want to handle this unhandled exception in my ModalService as I do not want to handle this case everytime I use the ModalService. It is always ok to close the modal via backdrop click, this is no exception.

I tried:

angular.module('myApp').service('ModalService', function($uibModal) {
  function open(options) {
    var modalInstance = $uibModal.open(options);
    modalInstance.result.catch(function error(error) {
      if(error === "backdrop click") {
        // do nothing
      } else {
        throw error;
      }
    })
    return modalInstance;
  }
});

But this leads to the problem that I cannot handle other errors than backdrop click as they are always thrown:

ModalService.open({...}).result.catch(function(error) {
  // this will catch the error too, but the throw in the ModalService
  // will occure in parallel and will not be catched by this function
});

And if I try it like this:

angular.module('myApp').service('ModalService', function($uibModal) {
  function open(options) {
    var modalInstance = $uibModal.open(options);
    modalInstance.result.then(function(whatever) {
      return whatever;
    }, function rejection(error) {
      return error;
    });
    return modalInstance;
  });
});

it resolves the 'unhandled rejection' error, but for every case not just for 'backdrop clicked'.

Has anybody a good solution for this case?

回答1:

Unfortunately that's how they handle it in The official Plucker for Modal (ui.bootstrap.modal).

If you click on any button it logs something like this:

Modal dismissed at: Thu Feb 23 2017 21:54:26 GMT-0300 (Pacific SA Daylight Time)

What they do is:

modalInstance.result.then(function (selectedItem) {
  $ctrl.selected = selectedItem;
}, function () {
  $log.info('Modal dismissed at: ' + new Date());
});

If you remove the error callback, guess what you get:

Possibly unhandled rejection: backdrop click

And even on cancel

Possibly unhandled rejection: cancel

So far, you either do that or use this workaround to silence unhandled rejections

app.config(['$qProvider', function ($qProvider) {
            $qProvider.errorOnUnhandledRejections(false);
        }]);


回答2:

use this

 $uibModal.open({
                    ////your code......
}).result.then(function(){}, function(res){})

now it will not give you error



回答3:

UI Specification dependent.

This is NOT the greatest workaround if there are UI specifications that the end-user must be able to click OUTSIDE the modal to close the modal.

If that is NOT the case and there is a little 'x' on the top right of the modal and/or there is a close

backdrop: false, // <<< !!!!!!! (see code below)
will prevent the end-user from clicking OUTSIDE the modal to close the modal.

$scope.change = function (changeableData, p_Mode) {
    var modalInstance = $uibModal.open({
        templateUrl: whatever,
        controller: ModalInstanceCtrl,
        scope: $scope,
        backdrop: false,  // <<< !!!!!!!
        resolve: {
            // whatever
        }
    });  

This will prevent the error "Possibly unhandled rejection: backdrop click" from occurring.

Once again, you need to look at the UI specifications and/or get permission from the analysts to implement this.



回答4:

If you're using a controller within your modal. I used this on the closing event. Because 'Closing' is valid but 'Dismissing' is a rejection. This goes within your modal controller, not the parent.

            $scope.$on('modal.closing', (event, reason, closed) => {
                if (!closed) {
                    event.preventDefault();
                    $scope.$close("Closing");   
                }

            });

So your backdrop click will fire the closing event but closed will be passed false. If that's the case, prevent the default behaviour, and programmatically close the modal instead of dismiss. Bare in mind this will break use of dismiss, if you want to use it for its original purpose.