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-запрос, а затем десериализовать ответ в функции обратного вызова.
В качестве примера, вот как я бы перестроил пример в ОП:
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().