0

I am looking for generic way for handling all the http errors in angular js. I do not want to handle errors on each controller to display the error message.

I know we can use generic exception handler and I have used interceptors in my application but currently it is only handling the "Unauthorized" failures and redirecting to login page. but for other failures I do not want to redirect but just display the error message.

How can I use generic exception handler to display the error message from the server on the UI for each screen?

ankit kothari
  • 359
  • 1
  • 3
  • 16
  • That is fine but how should I display errors messages from server for each UI screen from that .catch handler ? – ankit kothari Aug 12 '17 at 16:01
  • What do you want the user to experience? Users despise the disruptive interruption of modal dialogs. – georgeawg Aug 12 '17 at 16:42
  • User should know that their action failed on the server for e.g User creation failed due to duplicate email Id in the application so how should I display errors messages from server for each UI screen from that .catch handler ? – ankit kothari Aug 12 '17 at 16:52
  • Failures in form submission should be handled by the form controller with specific annotation on the form explaining to the user what needs correction. The [ngFormController](https://docs.angularjs.org/api/ng/type/form.FormController) and the [ngModelController](https://docs.angularjs.org/api/ng/type/ngModel.NgModelController) have mechanisms to facilitate such forms. For more information, see [AngularJS Developer Reference - Forms](https://docs.angularjs.org/guide/forms). – georgeawg Aug 12 '17 at 17:04
  • Consider using using the [$asyncValidators API](https://docs.angularjs.org/api/ng/type/ngModel.NgModelController#$asyncValidators) to check for duplicate email ids before form submission. – georgeawg Aug 12 '17 at 17:08

1 Answers1

0

You can use interceptors to handle this:

app.service('APIInterceptor', ['$rootScope', '$window', '$q', function($window, $q) {
    this.responseError = function(response) {
        if (response.status === 401 || response.status === 403) {
            $window.location.href = '/';

            return  ̶$̶q̶.̶r̶e̶j̶e̶c̶t̶(̶ response;
        } else if (response.status === 500) {
            $rootScope.$emit("appError", new Error('An error occurred'));

            return;
        }

        return  ̶$̶q̶.̶r̶e̶s̶o̶l̶v̶e̶ $q.reject(response);
    };
}]);

app.config(['$routeProvider', '$httpProvider', function($routeProvider, $httpProvider) {
    $httpProvider.interceptors.push('APIInterceptor');

// Some code here...

}]);

app.controller('MyController', ['$rootScope', '$scope', '$http', function($rootScope, $scope, $http) {
    $scope.errorMessage = '';

    $rootScope.$on('appError', function(e, error) {
        // Event details
        console.log(e);

        // Error object from interceptor
        console.log(error);
        $scope.errorMessage = error.message;
    });
}]);

Check AngularJS $http Service API Reference for more information.

M3talM0nk3y
  • 1,382
  • 14
  • 22
  • That is fine but how should I display errors messages from server for each UI screen from that $q.reject(response) ? Should I keep ng-model="errorMsg" on each screen and set $rootScope.errorMsg in that Interceptor ?In that case I need to reset errorMsg variable during screen navigation or some other approach ? – ankit kothari Aug 12 '17 at 16:06
  • You shouldn't need an errorMsg in the $rootScope; your controller can have an errorMsg and its $scope and you can set it once you handle the error. Check the answer on [AngularJS with global $http error handling](https://stackoverflow.com/a/37449792/5395709) for more details. – M3talM0nk3y Aug 12 '17 at 16:33
  • But I don't want my controller to handle the error.I am looking for more maintainable code in which global exception handle emit an error message and the current UI screen listen to it and display the error message. – ankit kothari Aug 12 '17 at 17:09
  • @ankitkothari Okay, that's understandable. In such case, you can emit an event from the interceptor and have a listener for it within your controller. I've updated the code example to reflect this. – M3talM0nk3y Aug 12 '17 at 20:56
  • Great ! Thank you so much for your help. – ankit kothari Aug 13 '17 at 03:31