Глобальний обробник помилок Ajax з AngularJS


82

Коли мій веб-сайт був на 100% jQuery, я робив це:

$.ajaxSetup({
    global: true,
    error: function(xhr, status, err) {
        if (xhr.status == 401) {
           window.location = "./index.html";
        }
    }
});

встановити глобальний обробник для 401 помилок. Тепер я використовую angularjs з $resourceі $httpдля виконання своїх (REST) ​​запитів на сервері. Чи є спосіб подібним чином встановити глобальний обробник помилок з angular?


Чи можливий дублікат AngularJS Failed Resource GET ?
— MilkyWayJoe

1
Ні, ми хочемо зробити глобальний обробник помилок 401 для програми
— cricardol

ха-ха, ти вважав, що ти хочеш, але з іншим статусом http (який ти можеш змінити)? Так чи інакше, відповідь pkozlowski.opensource показує, як це зробити
— MilkyWayJoe

Ні, це набагато більше схоже на відповідь Юстена ... це не дублікат запитання, про яке ви говорите
— cricardol

Відповіді:


97

Я також будую веб-сайт з кутовим, і я зіткнувся з цією ж перешкодою для глобальної обробки 401. У підсумку я використав перехоплювач http, коли натрапив на цю публікацію в блозі. Можливо, ви знайдете це так само корисно, як і я.

"Аутентифікація в додатку на основі AngularJS (або подібного)." , espeo програмне забезпечення

EDIT: остаточне рішення

angular.module('myApp', ['myApp.filters', 'myApp.services', 'myApp.directives'], function ($routeProvider, $locationProvider, $httpProvider) {

    var interceptor = ['$rootScope', '$q', function (scope, $q) {

        function success(response) {
            return response;
        }

        function error(response) {
            var status = response.status;

            if (status == 401) {
                window.location = "./index.html";
                return;
            }
            // otherwise
            return $q.reject(response);

        }

        return function (promise) {
            return promise.then(success, error);
        }

    }];
    $httpProvider.responseInterceptors.push(interceptor);

4
Потрібно повернути $ q.reject (відповідь); коли статус == 401, щоб уникнути шумної кутової помилки
— s_t_e_v_e

1
@daniellmb. Це залежить. Якщо ви насправді хочете перейти на іншу сторінку, а не просто змінити вигляд, тоді вам слід скористатися $ window. Якщо ваша сторінка входу - це просто інший вигляд та контролер з вашим
— angular,

1
Правильно, @uriDium, я мав на увазі використовувати кутові передбачені об’єкти, щоб ви могли знущатись і тестувати.
— daniellmb

22
$ httpProvider.responseInterceptors тепер застарілий. Див. Docs.angularjs.org/api/ng.$http#description_interceptors .
— кварцмо

1
Успішно вам потрібно повернути return response || $q.when(response);так, щоб, якщо відповідь порожня, тоді також повертався об'єкт-обіцянка.
— Ashish Gaur,

77

Зверніть увагу, що responseInterceptors застаріли за допомогою Angular 1.1.4. Нижче ви можете знайти фрагмент, заснований на офіційних документах , що демонструє новий спосіб реалізації перехоплювачів.

$provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {
  return {
    'response': function(response) {
      // do something on success
      return response || $q.when(response);
    },

   'responseError': function(rejection) {
      // do something on error
      if (canRecover(rejection)) {
        return responseOrNewPromise;
      }
      return $q.reject(rejection);
    }
  };
});

$httpProvider.interceptors.push('myHttpInterceptor');

Ось як це виглядає в моєму проекті за допомогою Coffeescript:

angular.module("globalErrors", ['appStateModule']).factory "myHttpInterceptor", ($q, $log, growl) ->
  response: (response) ->
    $log.debug "success with status #{response.status}"
    response || $q.when response

  responseError: (rejection) ->
    $log.debug "error with status #{rejection.status} and data: #{rejection.data['message']}"
    switch rejection.status
      when 403
        growl.addErrorMessage "You don't have the right to do this"
      when 0
        growl.addErrorMessage "No connection, internet is down?"
      else
        growl.addErrorMessage "#{rejection.data['message']}"

    # do something on error
    $q.reject rejection

.config ($provide, $httpProvider) ->
  $httpProvider.interceptors.push('myHttpInterceptor')

Але у вас не буде даних xhr чи іншої корисної інформації як перехоплювач responseError. Навіть неможливо вирішити, чи можна це відновити.
— zw0rk,

1
@ zw0rk Ви ... всередині responseError, rejectionмаєте все необхідне.
— Ленґдон,

$httpProvider...Цей останній рядок загортається в config()блок?
— delwin

справді, я відредагував свою відповідь, щоб показати, як я це зробив у своєму проекті за допомогою Coffeescript. Використовуйте js2coffee.org, якщо вам більше подобається в Javascript.
— MikeR

Якщо не всі посилання на responseпід responseErrorфункції на насправді бути посилання на rejection(або , можливо , параметр повинен бути його назва було змінено на response?
— Adam Нофсінгер

16

Створіть файл <script type="text/javascript" src="../js/config/httpInterceptor.js" ></script>із таким вмістом:

(function(){
  var httpInterceptor = function ($provide, $httpProvider) {
    $provide.factory('httpInterceptor', function ($q) {
      return {
        response: function (response) {
          return response || $q.when(response);
        },
        responseError: function (rejection) {
          if(rejection.status === 401) {
            // you are not autorized
          }
          return $q.reject(rejection);
        }
      };
    });
    $httpProvider.interceptors.push('httpInterceptor');
  };
  angular.module("myModule").config(httpInterceptor);
}());

@ThilakRaj наведений вище код повинен працювати на кожному http-запиті. Тож зробіть дві точки зупинки в Chrome, одну на рядку «відповідь на повернення» і одну на «повернення $ q.reject», щоб перевірити, чи працює вона належним чином.
— Jan-Terje Sørensen
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.