2013-12-14 3 views
2

У меня есть система сообщений, которая имеет два метода: show и clear. Я хочу использовать $ http-перехватчики для обработки аутентификации, потому что мой сервер достаточно умен, чтобы узнать, аутентифицирован ли пользователь или нет, и скажет мне, отправив мне ответ на состояние 401 или 403. Итак, у меня есть что-то подобное для моего перехватчика:Глобальная служба сообщений и аутентификация AngularJs

myModule.factory('statusInterceptor', function($location, MessageService, urlManager){ 
    return { 
     responseError: function(response){ 
      switch(response.status){ 
       ... 
       case 401: 
       case 403: 
        $location.url(urlManager.reverse('Login')); 
        MessageService.show('Dude, you need to log in first.'); 
        break; 
       case 500: 
        break; 
       ... 
      } 
      return response; 
     } 
    }; 
}); 

Это работает просто отлично либо на 401 или 403 ответ, как это показывает сообщение, как ожидалось. Проблема, с которой я столкнулась, - очищать сообщение, когда пользователь входит в систему или переходит на другой маршрут. У меня есть MainCtrl, который отвечает за почти все, и одна из вещей, за которыми он заботится, - $routeChangeStart. Я думал, что представление меняется на другое представление, поэтому я хочу очистить сообщения в начале маршрутного переключателя. Так, в моем MainCtrl у меня есть:

myControllers.controller('MainCtrl', function($scope, MessageService){ 
    $scope.$on('$routeChangeStart', function(){ 
     MessageService.clear(); 
    }); 
}); 

Вот как я ожидаю, что приложение реагирует:

  1. Пользователь пытался сделать что-то без проверки подлинности, отправив запрос на сервер
  2. Сервер отвечает либо 401, либо 403, поскольку пользователь не аутентифицирован.
  3. У меня есть функция responseError, вызывающая мой метод $location.url(), который, на мой взгляд, должен стрелять $routeChangeStart или даже $locationChangeStart, события (я пробовал оба).
    • Это должно в свою очередь запустить мой метод MessageService.clear() и удалить все предыдущее сообщение.
  4. Пользователь, наконец, перенаправляется на страницу входа с правильным сообщением "Dude, you need to log in first.".

Что происходит на самом деле:

Пользователь перенаправляется на страницу входа в систему, как и ожидалось, однако, сообщение об ошибке не отображается. При настройке определенных точек отладки в Chrome я вижу, что сразу вызывается $location.path(), а затем MessageService.show('Dude...'), после чего следует звонок MessageService.clear().

ответ

1

Может быть, вам нравится этот подход к этой проблеме

http://jsfiddle.net/jYCPQ/1/

module.factory('authenticationInterceptor', function ($q, navigator, MessageService) { 
    return { 
     responseError: function (response) { 
      switch (response.status) { 
       case 403: 
        navigator.navigateTo("/login").then(function() { 
         MessageService.show('Dude, you need to log in first.'); 
        }); 
        return $q.reject(response); 
      } 
      return response; 
     } 
    }; 
}); 
module.factory("navigator", function ($location, $rootScope, $q) { 

    var navigateTo = function (url) { 
     var defered = $q.defer(); 
     $location.url(url); 
     var unbind = $rootScope.$on('$routeChangeSuccess', function() { 
      defered.resolve(); 
      unbind(); 
     }) 
     return defered.promise; 
    } 
    return { 
     navigateTo: navigateTo 
    } 
}); 

С уважением

+0

Мне нравится использование в $ д обещании. Я не знал, что вы можете использовать его для чего-либо другого, кроме событий запроса/ответа. Итак, $ q - это просто более простой способ сделать обратные вызовы? – OozeMeister

+0

да :) ознакомьтесь с документацией – kfis

1

я, наконец, нашел решение, и в конечном итоге с чем-то вроде этого:

В моей перехватчик функции:

myModule.factory('statusInterceptor', function($rootScope){ 
    return { 
     responseError: function(response){ 
      switch(response.status){ 
       ... 
       case 401: 
       case 403: 
        $rootScope.$broadcast('event:notAuthenticated'); 
        break; 
       case 500: 
        break; 
       ... 
      } 
      return response; 
     } 
    }; 
}); 

И в мой контроллер:

myControllers.controller('MainCtrl', function($scope, $location, MessageService){ 
    $scope.$on('event:notAuthenticated', function(){ 
     $location.path(urlManager.reverse('Login')); 
     var remove_this_binding = $scope.$on('$routeChangeSuccess', function(){ 
      messageService.show('Dude, you need to log in first.'); 
      remove_this_binding(); 
     }); 
    }); 
    $scope.$on('$routeChangeStart', function(){ 
     messageService.clear(); 
    }); 
}); 

Я пытался найти угловой способ иметь обратный вызов, связанный с изменением пути $location, и это лучшее, что я мог придумать. Если у кого-то еще есть лучшее решение, я все уши.

Смежные вопросы