在AngularJs中使用$ http预加载数据的最佳方法

时间:2014-10-10 01:53:36

标签: angularjs angularjs-service angular-promise angular-http

我正在尝试创建一个服务,该服务首先通过使用$ 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调用,但有什么更好的吗?可以承诺在这种情况下以更好的方式使用吗?

3 个答案:

答案 0 :(得分: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']);
    });
}]);

答案 1 :(得分: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);
});

答案 2 :(得分: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。

返回的承诺