angular-http-auth с $http transformResponse

Я использую angular-http-auth для отображения диалогового окна входа в систему всякий раз, когда 401 "неавторизованный" ответ возвращается с сервера.

Поскольку я крут, я также пытаюсь десериализовать объекты ответа в моих сервисах. Например, если служба запрашивает car и ответ {make: Honda, model: Civic}Я пытаюсь десериализовать это в Car использование объекта transformResponse,

Например:

getCar: function() {
    return $http.get('/api/car', {
        method: 'GET',
        transformResponse: function(data, headers) {
            var c = angular.fromJson(data);
            return new Car(c);
        }
    });
}

Это не работает с angular-http-auth. Если ответ был 401 Несанкционированный, вы получите ошибку JavaScript. Это потому, что Angular попытается запустить transformResponse код, даже если ответ был 401.

Оказывается, что $http перехватчики (которые использует angular-http-auth) запускаются ПОСЛЕ transformResponse код. Это огромная проблема, потому что ни один из этого кода в transformResponse будет работать, если ответ сервера был 401 (не было бы data)

Это проблема для кого-то еще? Как ты справился с этим? Я не использовать transformResponse если я использую $http перехватчики?

2 ответа

Решение

Я знаю, что поздно вечером на вечеринке, но для тех, кто пришел сюда из Google, как я (я также опубликовал это в качестве комментария к связанной проблеме, поданной в репо Angular):

Я также нашел, что это сбивает с толку, что перехватчики ответа запускаются после transformResponse метод. Я добавил метод $http.defaults.transformResponse, Вот пример из документации о том, как это сделать.

Итак, если вам нужно в основном иметь перехватчик ответа, который запускается до transformResponse Метод, это должно сделать это:

'use strict';

angular.module('app')
  .run(function ($http) {
    $http.defaults.transformResponse.push(function (data, headers) {
      // do stuff here before the response transformation

      // Be sure to return `data` so that the next function in the queue can use it.
      // Your services won't load otherwise!
      return data;
    });
  });

Если ваши сервисы или http-вызовы не имеют своего собственного преобразователя ответа, вы в порядке.

Если ваши услуги имеют свои transformResponse метод, они на самом деле переопределят все преобразователи по умолчанию (я узнал об этом после долгого чтения документации), и приведенный выше код не будет работать.

Чтобы обойти это, вы можете следовать этому примеру в документации.

Чтобы обойти эту проблему, я не использую transformResponse больше. Я просто не вижу смысла transformResponse если он работает до $ http перехватчиков.

Чтобы использовать angular-http-auth, а также десериализовать ответы в ваших сервисах, вы можете написать свои сервисы, чтобы они сначала выполняли HTTP-запрос, а затем десериализовать ответ в функции обратного вызова.

В качестве примера, вот как я бы перестроил пример в ОП:

Plunker

services.factory('HttpCarService', function($resource, $q) {
  var resource = $resource('/api/car');

  return {

    getCar: function() {

      var deferred = $q.defer();
      var car = null;

      var successCallback = function(data, status, headers, config) {
        var c = angular.fromJson(data);
        car = new Car(c);
        deferred.resolve(car);
      };

      var errorCallback = function(data, status, headers, config) {
        deferred.reject("something wrong");
      };

      var result = resource.get(successCallback, errorCallback);
      return deferred.promise;
    }
  };

});

Этот шаблон также будет работать, если data это массив.

$http перехватчики будут работать до того, как будет выполнен любой из методов обратного вызова. Если вашему $ resource нужны параметры url, вы можете заставить функцию getCar() принимать объект конфигурации в качестве параметра и передавать необходимую информацию о том, когда вы делаете вызов $resource.get().

Другие вопросы по тегам