Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Handling error in AngularJS when consuming WebApi

In the code below, I'd like handling errors :

  • 401 : redirect to a login page
  • other : display error message (received in the message of the error)

I don't find the right way to do this.

Any idea ?

Thanks,

Module.js

var app;  
(function () {  
    app = angular.module("studentModule", []);  
})() 

Service.js

app.service('StudentService', function ($http) {    
    this.getAllStudent = function () {  
        return $http.get("http://myserver/api/Student/");  
    }  
});

Controller.js

app.controller('studentController', function ($scope, StudentService) { 

    function GetAllRecords() {  
        var promiseGet = StudentService.getAllStudent();  
        promiseGet.then(function (pl) { $scope.Students = pl.data },  
              function (errorPl) {  
                  $log.error('Some Error in Getting Records.', errorPl);  
              });  
    } 

});
like image 309
Kris-I Avatar asked May 03 '26 19:05

Kris-I


1 Answers

As with most problems, there are many different ways to handle errors from AJAX requests in AngularJS. The easiest is to use an HTTP interceptor as already pointed out. This can handle both authentication and errors.

app.config(['$httpProvider', function($httpProvider) {
  $httpProvider.interceptors.push(['$rootScope', '$q', function($rootScope, $q) {

    return {
      responseError: function(rejection) {
        var deferred;

        // If rejection is due to user not being authenticated
        if ( rejection.status === 401 ) {

          $rootScope.$broadcast('unauthenticated', rejection);

          // Return a new promise since this error can be recovered
          // from, like redirecting to login page. The rejection and
          // and promise could potentially be stored to be re-run
          // after user is authenticated.
          deferred = $q.defer();
          return deferred.promise;
        }

        $rootScope.$broadcast('serverError', rejection);
        // Just reject since this probably isn't recoverable from
        return $q.reject(rejection);

      }
    }
  };
}]);

The above interceptor is created using an anonymous function but factories can be used to handle one or many different interceptors. The AngularJS docs have decent information about how to write different ones: https://docs.angularjs.org/api/ng/service/$http#interceptors

With the interceptors in place, you now just need to listen from the broadcasted events in your run method or any controller.

app.run(['$rootScope', '$location', function($rootScope, $location) {

  $rootScope.$on('unauthenticated', function(response) {
    // Redirect to login page
    $location.path('/login');
  });

  $rootScope.$on('serverError', function(response) {
    // Show alert or something to give feedback to user that
    // server error was encountered and they need to retry
    // or just display this somewhere on the page
    $rootScope.serverError = response.data.errorMessage;
  });
}]);

In your view:

<body ng-app="studentModule">
  <div id="server_error" ng-if="!!serverError">{{serverError}}</div>
  ...rest of your page
</body>

Like almost all AngularJS code, most of this can be abstracted into different factories and services but this should be a good place to start.

like image 136
rsnorman15 Avatar answered May 05 '26 10:05

rsnorman15