0

我正在构建的角度应用程序有一个非常奇怪的问题。每当我从如下定义的资源中加载一些数据时(我可以构建的最简单的示例),我都会返回一些数据,我可以将其用于数据绑定(例如 ng-repeat='message in messages' 或作为 {{message.id}} ) 但是我永远无法通过将其作为数组或对象访问来从 javascript 中读取它(取决于我使用 get({id:myId}) 还是 query())。

迭代它只会给我 $get、$query、$save 等键......但没有实际数据。

app.factory('Message', ['$resource', function($resource) {
    return $resource('MY_URL/messages/:id', {id: '@id'});
}]);

app.service('messageService', ['$rootScope', 'Message', function($rootScope, Message) {
    var messages = Message.query();
    var selectedMessage = null;

    var service = {};

    service.get = function(id) {
                    // Problem A (see below for details)
        if (arguments.length === 1) return Message.get({id: id});
        else return messages;
    };

var MenuCtrl = function($scope, Project, messageService, otherService) {
    $scope.projects = Project.query();
    $scope.messages = messageService.get();

    // Problem B (details below)
};

在问题 A 中,我希望能够从已经获取的集合中返回单个元素,但是我需要一些方法来处理在数据准备好之前发生的调用。

在问题 B 我想处理一些获取的数据并将结果传递给“otherService”但是我需要一种方法来延迟这个直到数据准备好。

4

1 回答 1

1

我只在单元测试中看到过这个问题,解决它的方法是“刷新”模拟 $httpBackend。

根据API 文档

生产中使用的 $httpBackend 总是以异步方式响应请求。如果我们在单元测试中保留这种行为,我们将不得不创建异步单元测试,这很难编写、遵循和维护。同时测试模拟,不能同步响应,因为这会改变被测代码的执行。出于这个原因,模拟 $httpBackend 有一个 flush() 方法,它允许测试显式地刷新挂起的请求,从而保留后端的异步 api,同时允许测试同步执行。

这是一个带有一些上下文的示例:

// define a resource within a service
angular.module('app.services', ['ngResource'])
  .factory('Message', function ($resource) {
    var url = ...
      , params = ...
      , actions = ...;

    return $resource(url, params, actions);
  }

// Query the resource in a controller
function MessagesCtrl ($scope, $routeParams, Message) {
  $scope.messages = Message.query();
}

// unit test with a mocked backend
describe('MessagesCtrl', function() {
  var scope, ctrl, $httpBackend, messages;

  beforeEach(inject(function (_$httpBackend_, $rootScope, $controller) {
    $httpBackend = _$httpBackend_;
    scope = $rootScope.$new();

    messages = [
      {
        id: '1',
        text: 'foo',
      }, {
        id: '2',
        text: 'foo',
      }
    ]

    $httpBackend.expectGET('/api/messages').respond(messages);
    ctrl = $controller('MessagesCtrl', {$scope: scope});
  }));

  it('should get a list of messages', function () {

    // THE NEXT LINE WILL SOLVE THE PROBLEM
    $httpBackend.flush();

    expect(scope.message).toEqualData(message);
  });
});
于 2012-11-23T18:40:50.957 回答