Угловой манипулятор AngularJS 404s

У меня есть приложение со службой, которая завершает мои вызовы API:

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) {
                console.log('ConcernService.get status',status);
                defer.reject(status);
            });
        return defer.promise;
    },

и я использую UI-Router для перехода между состояниями:

concernsApp

    .config( function ($stateProvider, $urlRouterProvider) {

        $urlRouterProvider.otherwise("/404/");


        $stateProvider.state('project', {
        url: '/project/:projectId/',
        resolve: {
            project: function ($stateParams, ConcernService) {
                return ConcernService.get('projects/', $stateParams.projectId);
            },
        },
        views: {
            ...
        }
    });

Я перехожу от обычного маршрутизатора AngularJS, и мне трудно понять, как реализовать 404s. Я вижу, как ConcernService выбрасывает статус console.log как отклоненный, но как его улавливать в государственном маршрутизаторе?

Любая помощь очень ценится.

Ответы

Ответ 1

Правило otherwise() вызывается только тогда, когда нет другого маршрута. То, что вы действительно хотите, - это перехватить событие $stateChangeError, которое запускается, когда что-то происходит неправильно при переходе состояния (например, при неудачном решении). Подробнее об этом можно узнать в документах изменений состояния изменений.

Простейшая реализация того, что вы пытаетесь сделать, будет примерно такой:

$rootScope.$on('$stateChangeError', function(event) {
  $state.go('404');
});

Кроме того, поскольку $http сам построен на promises (который разрешает resolve), ваш метод ConcernService можно упростить до однострочного (я понимаю, вы расширили его для целей отладки, но вы мог бы так же легко скопировать его, просто FYI):

var ConcernService = {

  get: function (items_url, objId) {
    return $http.get(api_url + items_url + objId);
  }
}

Ответ 2

Я различаю между двумя 404 состояниями:

Сервер

  • показать 404 страницы в зависимости от ответа сервера HTTP-код 404
  • важно определить нет URL-адрес, чтобы пользователь оставался на URL-адресу, где произошла ошибка.

Client

  • URL не найден angular ui router (ни один из определенных URL-адресов)

Код для angular Состояние пользовательского интерфейса:

$stateProvider
  .state('404server', {
    templateUrl: '/views/layouts/404.html'
  })
  .state('404client', {
    url: '*path',
    templateUrl: '/views/layouts/404.html'
  });

Код в $httpProvider перехватчике:

if(response.status === 404) {
  $injector.get('$state').go('404server');
}

И почему я использовал $injector вместо $state, объясняется здесь.

Ответ 3

Вы также можете попробовать что-то подобное и посмотреть, работает ли оно для вас. Возможно, вам придется приспособиться к вашим потребностям:

.state('otherwise', {
    abstract: true,
    templateUrl: 'views/404.html'
})
.state('otherwise.404', {
    url: '*path',
    templateUrl: 'views/404.html'
})

Ответ 4

$urlRouterProvider работает только как $watch to $location, и если фактический URL-адрес соответствует одному из правил, определенных в функции .config(), он перенаправляется на указанный маршрут.

Здесь, что я рекомендую, определите "/404/" как состояние:

$stateProvider.state('404', {
  url:'/404/',
  views:{
      ...
  }
});

И внутри функции reject() перейдите в состояние 404

 if(status == '404'){
   $state.transitionTo('404');
 }

Вам нужно будет добавить ui-router в качестве зависимости от модуля проекта и использовать поставщик $state в вашем контроллере, чтобы иметь возможность использовать $state.transitionTo()

Вот некоторая информация: https://github.com/angular-ui/ui-router/wiki/Quick-Reference#statetransitiontoto-toparams--options

Ответ 5

Мне удалось обработать 404 без использования $urlRoutProvider, так как я только использую состояния, тестируя $state.transistion:

angular.module("app", []).run(["$state", "$rootScope", function($state, $rootScope) => {
    $rootScope.$on("$locationChangeSuccess", function() {
        if (!$state.transition) {
            $state.go("404");
        }
    });
}]);

Ответ 6

$urlRouterProvider.otherwise('/page-not-found');

.state('error', {
  url: "/page-not-found",
  templateUrl: "templates/error.html",
  controller: "errorController"
})

Будет обрабатывать вашу страницу, не найденную проблему.

Если вы хотите поднять 404, используйте целенаправленное использование состояния или URL-адреса. Мы создали отдельный контроллер, только если вы хотите выполнять какие-либо операции.