1

我正在尝试创建一个服务,该服务首先通过使用 $http 进行 AJAX 调用来加载一些数据。

我正在看类似的东西:

app.factory('entityFactory', function() {
    var service = {};

    var entities = {};

    // Load the entities using $http

    service.getEntityById(entityId)
    {
        return entities[entityId];
    }

    return service;
});

app.controller('EntityController', ['$scope', '$routeParams', 'entityFactory', function($scope, $routeParams, entityFactory) {
    $scope.entity = entityFactory.getEntityById($routeParams['entityId']);
}]);

我想确保在使用返回实体之前完全加载实体getEntityById

请让我知道这样做的正确方法是什么?我知道的一种方法是进行同步 AJAX 调用,但有更好的方法吗?在这种情况下可以以更好的方式使用 Promise 吗?

4

3 回答 3

1

尝试使用 $q 检查服务是否已初始化。对我来说足够干净,欢迎任何其他方法:)。

app.factory('entityFactory', function($q, $http) {
    var service = {};

    var _entities = {};
    var _initialized = $q.defer();

    $http({method: 'GET', url: '/getData'})
        .success(function(data, status, headers, config) {
            if (data.success)
            {
                _entities = data.entities;
            }

            _initialized.resolve(true);
        })
        .error(function(data, status, headers, config) {
            _initialized.reject('Unexpected error occurred :(.');
        });

    service.getEntityById(entityId)
    {
        return entities[entityId];
    }

    service.initialized = _initialized.promise;

    return service;
});

app.controller('EntityController', ['$scope', '$routeParams', 'entityFactory', function($scope, $routeParams, entityFactory) {
    entityFactory.initialized.then(function() {
        $scope.entity = entityFactory.getEntityById($routeParams['entityId']);
    });
}]);
于 2014-10-10T02:37:47.953 回答
0

传入回调或调用$q.defer()通常表明您没有利用承诺链。我认为执行您所要求的合理方法如下。

app.factory('entityFactory', function($http) {
  var service = {};

  var _entitiesPromise = $http({method: 'GET', url: '/getData'});

  service.getEntityById = function(entityId) {
    return _entitiesPromise.then(function(results) {
      return results.data.entities[entityId];
    });
  };

  return service;
});

app.controller('EntityController', ['$scope', '$routeParams', 'entityFactory', function($scope, $routeParams, entityFactory) {
  entityFactory.getEntityById($routeParams['entityId']).then(function(entity) {
    $scope.entity = entity;
  }, function() {
    // Can still do something in case the original $http call failed
  });
}]);

你只缓存从 $http 返回的承诺。

于 2014-10-10T07:07:40.353 回答
0

您可以利用工厂内的回调在第一次调用时存储数据,然后在每次后续调用时从服务接收数据:

app.factory('entityFactory', function() {
    var service = {};

    var entities = null;

    // Load the entities using $http
    service.getEntityById(entityId, callback)
    {
        if (entities == null) {
            $http(options).success(function(data) {
                entities = data;
                callback(data);
            });
        } else {
            callback(entities);
        }
    }

    return service;
});

然后你可以使用这个:

entityFactory.getEntityById(id, function(entities) {
    //console.log(entities);
});
于 2014-10-10T02:27:11.503 回答