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?

6
  • which version of angular you are using ?? Commented Feb 20, 2014 at 20:26
  • Angular version 1.2.9 Commented Feb 20, 2014 at 20:50
  • 1
    Looks like you're mixing interceptors with response interceptors (deprecated). The error you're getting is at return promise.then(... promise isn't defined there. docs.angularjs.org/api/ng/service/$http Commented Feb 20, 2014 at 20:51
  • You are using depreceated definition kindly refer to new syntax Commented Feb 20, 2014 at 20:53
  • Can you give me some idea of what this would look like using the new inceptor syntax? Commented Feb 20, 2014 at 22:16

3 Answers 3

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.

Sign up to request clarification or add additional context in comments.

2 Comments

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=...'
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.
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.

3 Comments

Actually, I pulled the interceptor code from here: djds4rce.wordpress.com/2013/08/13/… Only changed the 401 to 404.
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..
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.
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>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.