4

每当从服务器返回 401“未经授权”响应时,我都会使用angular-http-auth显示登录对话框。

由于我很酷,我还尝试在我的服务中反序列化响应对象。例如,如果一个服务请求 acar并且响应是{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 Unauthorized,您将收到一个 javascript 错误。transformResponse这是因为即使响应是 401 ,Angular 也会尝试运行该代码。

事实证明,$http拦截器(这是angular-http-auth使用的)在transformResponse代码之后运行。transformResponse这是一个大问题,因为如果服务器响应是 401(不会有任何 401 data),那么这些代码都不会起作用

这对其他人来说是个问题吗?你是怎么解决的?transformResponse如果我使用$http拦截器,我不使用吗?

4

2 回答 2

4

我知道,派对迟到了,但是对于像我一样从谷歌来到这里的任何人(我也发布了这个作为对 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方法,它们实际上会覆盖所有默认转换器(我在长时间阅读文档后发现了这一点),并且上面的代码将无法运行。

为了避免这种情况,您可以按照文档中的这个示例进行操作。

于 2016-01-26T23:49:04.583 回答
1

为了解决这个问题,我不再使用transformResponse了。我只是看不出transformResponse它是否在 $http 拦截器之前运行。

为了在您的服务中使用angular-http-auth并反序列化响应,您可以编写您的服务,以便它们首先执行 HTTP 请求,然后在回调函数中反序列化响应。

例如,以下是我将如何重组 OP 中的示例:

普朗克

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() 时传递必要的信息。

于 2014-08-30T18:01:58.283 回答