19

I have an Angular app, for which I want to handle 404s form an API end point. The key components are like so:

// app.js

var myApp = angular.module('myApp', ['ngRoute',]);

myApp.config( function ($httpProvider, $interpolateProvider, $routeProvider) {
  $httpProvider.interceptors.push('httpRequestInterceptor');

  $routeProvider
    ...
    .when('/project/:projectId', {
        templateUrl : 'partials/project_detail.tmpl.html',
        controller: 'ProjectDetailCtrl',
        resolve: {
            project: function ($route, ConcernService) {
                return ConcernService.get('projects/', $route.current.params.projectId);
            },
        }
    });
});


// interceptors.js

myApp.factory('httpRequestInterceptor', function ($q, $location) {
  return {
    response: function(response){
      return promise.then(
        function success(response) {
          return response;
        },
        function error(response) {
          if(response.status === 404){
            $location.path('/404');
            return $q.reject(response);
          }
          else{
            return $q.reject(response); 
          }
        }
      );
    }
  };
});


// services.js

myApp.factory('ConcernService', function ($http, $q) {

var ConcernService = {
    ...
    get: function (items_url, objId) {
        var defer = $q.defer();
        $http({method: 'GET', 
            url: api_url + items_url + objId}).
            success(function (data, status, headers, config) {
                defer.resolve(data);
            }).error(function (data, status, headers, config) {
                // when API not found, status == 404 
                console.log('ConcernService.get status',status);
                defer.reject(status);
            });
        console.log('ConcernService.get promise',defer.promise);
        return defer.promise;
    },
}
});

The issue is I am getting an error of ReferenceError: promise is not defined at response. Is this because the ConcernService defers the promise? How should I deal with this?

halfer
  • 19,824
  • 17
  • 99
  • 186
Darwin Tech
  • 18,449
  • 38
  • 112
  • 187

3 Answers3

37

So, my solution which works, using the new interceptor syntax is as follows:

// interceptors.js

.factory('httpRequestInterceptor', function ($q, $location) {
    return {
        'responseError': function(rejection) {
            // do something on error
            if(rejection.status === 404){
                $location.path('/404/');                    
            }
            return $q.reject(rejection);
         }
     };
});


// app.js

myApp.config( function ($httpProvider, $interpolateProvider, $routeProvider) {
    $httpProvider.interceptors.push('httpRequestInterceptor');

    $routeProvider
    ...
    .when('/404/:projectId', {
        templateUrl : 'partials/404.tmpl.html',
        controller: '404Ctrl',
        resolve: {
            project: function ($route) {
                // return a dummy project, with only id populated
                return {id: $route.current.params.projectId};
            }
        }
    });
});


// 404.tmpl.html

...

<h1>Oh No! 404.</h1> 
<p>Project with ID {{ project.id }} does not exist.</p>

This is a simplified version, but demonstrates how I used the interceptor pattern to solve my issue.

Comments are welcome.

demisx
  • 7,217
  • 4
  • 45
  • 43
Darwin Tech
  • 18,449
  • 38
  • 112
  • 187
  • 1
    Does the $location.path in the interceptor factory actually update the location? This didn't work for me. I found it necessary to use '$window.location.href=...' – ericpeters0n Mar 14 '14 at 03:42
  • 1
    This answer has one critical problem. The return statement "return $q.reject(rejection);" should be outside IF block otherwise it would break the interceptor chain. – Amit Jan 04 '15 at 17:05
2

I think the structure of you interceptor might be off. I posted an answer with a sample interceptor here (Handle HTTP 302 response from proxy in angularjs) that you might find useful. It works for me on a daily basis.

Community
  • 1
  • 1
MBielski
  • 6,628
  • 3
  • 32
  • 43
  • Actually, I pulled the `interceptor` code from here: http://djds4rce.wordpress.com/2013/08/13/understanding-angular-http-interceptors/ Only changed the 401 to 404. – Darwin Tech Feb 20 '14 at 20:51
  • Also in your example, the `interceptor` gives out the partial and Controller. I would prefer to handle the `/404` using `ngRoute` in the app config.. – Darwin Tech Feb 20 '14 at 20:55
  • Yeah, we raise an alert dialog when we get 400 errors, hence the partial and controller. Obviously handling the 404 on the route would be a bit different. – MBielski Feb 20 '14 at 22:05
0

Is just easier to pass parameter as

<div class="fullPortfolio" ng-show="projectId.length">Project Id passed</div>

and then when project id is not exist

<div class="fullPortfolio" ng-show="!projectId.length">Project Id is not exist</div>

Digital Legend
  • 149
  • 1
  • 13