【问题标题】:angular-http-auth with $http transformResponseangular-http-auth 与 $http transformResponse
【发布时间】:2014-08-27 16:34:31
【问题描述】:

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

由于我很酷,我还尝试反序列化我的服务中的响应对象。例如,如果服务请求 car 并且响应是 {make: Honda, model: Civic},我尝试使用 transformResponse 将其反序列化为 Car 对象。

例如:

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 错误。这是因为 Angular 会尝试运行 transformResponse 代码,即使响应是 401。

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

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

【问题讨论】:

    标签: angularjs authentication angular-http-auth


    【解决方案1】:

    派对迟到了,我知道,但是对于像我一样从 Google 来到这里的任何人(我也将此作为评论发布在 related issue 提交到 Angular 存储库中):

    我还发现响应拦截器在transformResponse 方法之后运行 令人困惑。我向$http.defaults.transformResponse 添加了一个方法。 Here 是文档中有关如何执行此操作的示例。

    所以,如果您基本上需要有一个响应拦截器运行之前 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 方法,它们实际上会覆盖所有默认转换器(我在长时间阅读文档后发现了这一点),并且上面的代码不会运行。

    要避免这种情况,您可以在文档中关注this example

    【讨论】:

      【解决方案2】:

      为了解决这个问题,我不再使用transformResponse。如果transformResponse 在 $http 拦截器之前运行,我只是看不到它的意义。

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

      作为一个例子,这是我将如何在 OP 中重组示例:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-08-11
        • 2021-10-01
        • 2013-10-05
        • 1970-01-01
        • 1970-01-01
        • 2018-01-07
        • 2022-11-10
        • 1970-01-01
        相关资源
        最近更新 更多