响应拦截器数据不完整

时间:2016-01-12 16:44:46

标签: javascript angularjs

我有一个我无法理解的奇怪问题。我希望有人可以帮助我。

Plunker:http://plnkr.co/edit/e9B6jc - 由于某些原因,我无法在plunker中重现这种情况,但自创建之后,我将其保留在此处以显示预期的设置和数据。

设置如下:

  • 带API的服务器。
  • 带有角度的Web界面的服务器。

这个过程是这样的:

  1. 我向API(/api/employees/{guid})发出GET请求,该请求返回plunker中的employee.json之类的数据。我正在使用 ngResouce (angular-resource)来查询API。
  2. 它被 HttpInterceptor 截获,它为请求添加了一些必需的标题。
  3. 当服务器返回数据(服务器响应)时, HttpInterceptor 再次拦截响应。它会做一些事情并拒绝或继续,具体取决于状态。
  4. 继续时,数据只会传回控制器。
  5. 我的问题在3到4之间:当拦截响应时(3),我记录数据(如plunker的script.js所示,第35行),随机地,我得到{{1}空的。我确定角色数组不是空的,因为当我在开发人员工具(谷歌浏览器,网络选项卡)中检查数据时,响应包含所有数据。即使在API日志中(在服务器端),roles数组也不为空。

    奇怪的是,当我记录截获的响应时,response.data.account.roles可能为空(是的,并非总是如此)。但是,如果我显式地记录对象(使用response.data.account.roles),则数组永远不会为空。

    在UI中,我使用angular来显示完整的对象(plunker的index.html,第17行),有时account.roles为空。我有时说,因为当我重新加载页面时会发生这种情况。当然,这会导致UI出现问题,因为response.data.account.roles有时是空的,我需要它来设置select元素的选定项。

    我做了一些测试:

    • 在angular-resource.js中放置一个断点(执行响应的地方),response.data包含所有预期的角色。
    • 在$ http(config).transformResponse(私有方法)中的angular.js中添加另一个断点,并且响应(没有解析)再次完成(角色存在)。
    • 在httpInterceptor中,如果我执行响应对象的angular.copy,则会填充roles数组。

      response.data.account.roles

    在前2个测试中,响应包含预期的数据,但奇怪的是,在UI(和拦截器)中,roles数组为空。

    我希望有人可以启发我,因为我无法弄清楚:(顺便说一下,我也在谷歌小组中提出了这个问题 - > https://groups.google.com/forum/#!topic/angular/ecJmyjBOvvc

    感谢所有阅读此内容的人。

    plunker代码是:

    的script.js

    var copy = angular.copy(response);
    // copy.data.account.roles.length > 0 = true
    // response.data.account.roles.length > 0 = false
    

    mainController.js

    var app = angular.module('app', ['ngResource']);
    
    app.factory('HttpInterceptor', function($rootScope, $log, $q, $injector, $location) {
      var interceptor = {
        request: onRequest,
        requestError: onRequestError,
        response: onResponse,
        responseError: onResponseError
      };
      return interceptor;
    
      function onRequest(config) {
        $log.debug('Entering request.');
        config.headers['Accept-Language'] = 'es-cl';
        if (config.url.endsWith('.html')) {
          return config;
        }
        config.headers['Accept'] = 'application/json';
        var token = 'token data that comes from server';
        if (!angular.isUndefined(token)) {
          config.headers.Authorization = token;
        }
        $log.debug('Leaving request.');
        return config;
      }
    
      function onRequestError(error) {
        $log.error('Request failed.', error);
      }
    
      function onResponse(response) {
        $log.info('Response success.');
        // Roles array is empty
        // Here, when the account is present, the roles array MAY be empty
        $log.debug('Intercepted response data:', response);
        if (response) {
          if (response.data) {
            if (response.data.account) {
              // Data shown correctly
              // Here, when the account is present, the roles array ALWAYS has data
              // (of course, only when the roles is not empty)
              if (response.data.account.roles) {
                $log.debug('Roles:', response.data.account.roles);
              }
            }
          }
        }
    
        var copy = angular.copy(response);
        // copy.data.account.roles.length > 0 = true
        // response.data.account.roles > 0 = false (sometimes)
    
        return response || $q.when(response);
      }
    });
    

    jsonFactory.js

    angular.module('app').controller('mainCtrl', function($scope, $http, JsonFactory) {
      JsonFactory.get(function(data) {
        $scope.employee = data;
      });
    });
    

    employee.json(预期的服务器响应)

    angular.module('app').factory('JsonFactory', function($resource) {
      return $resource('employee.json');
    });
    

    的index.html

    {
      "id" : "employee-guid",
      "firstName" : "Test",
      "lastName" : "Subject",
      "nationalId" : "1-9",
      "account" : {
        "login" : "1-9",
        "email" : "a@a.com",
        "roles" : [
          {
            "id" : "role0-guid",
            "name" : "unpriv",
            "displayName" : "No permissions at all",
            "description" : "Some descriptive text"
          },
          {
            "id" : "role1-guid",
            "name" : "somepriv",
            "displayName" : "Some permissions",
            "description" : "Some descriptive text"
          }
        ]
      }
    }
    

    更新12-01-2016

    <!DOCTYPE html> <html> <head> <script data-require="angular.js@1.4.8" data-semver="1.4.8" src="https://code.angularjs.org/1.4.8/angular.js"></script> <script src="https://code.angularjs.org/1.4.8/angular-resource.js"></script> <link rel="stylesheet" href="style.css" /> <script src="script.js"></script> <script src="jsonFactory.js"></script> <script src="mainController.js"></script> </head> <body ng-app="app"> <div ng-controller="mainCtrl as ctrl"> <div> <h4>Employee</h4> <pre>{{ employee | json }}</pre> </div> <div> <h4>Roles</h4> <pre>{{ employee.account.roles | json }}</pre> </div> </div> </body> </html> 有时也可能为空。

    我知道copy.data.account.roles没有显示当前的对象状态,因此我使用断点来检查Google Chrome中的对象。

    Angular版本是1.4。

1 个答案:

答案 0 :(得分:0)

好吧,我解决了我的问题...问题是我正在使用的指令是删除数组的内容。

感谢所有花时间阅读此内容的人。