AngularJS服务延迟API调用

时间:2014-10-20 15:58:36

标签: javascript angularjs angular-services

我试图从GitHub仓库中获取国家列表而不将所有信息存储在JS或我自己的API中,所以我写了一个一次性服务来处理这个问题。我将结果缓存在浏览器中,以防再次需要它们。但是,我注意到我写的方式,$http.get被称为加载,而不是服务注入控制器 - 这意味着浏览器即使不需要,也会请求所有这些国家/地区数据(例如,即使用户访问国家/地区页面也是如此。

我构建这个的方式,因为服务只是返回一个承诺,我可以在控制器中调用countrylist.then(...)。有没有办法保持这一点,但仍然将请求延迟到Github,直到实际需要它?

以下代码:

angular.module('myModule')
    .factory('countrylist', ['$http', 'growl', '$q', function ($http, growl, $q) {

        var deferred = $q.defer();
        var flagUrl = "https://raw.githubusercontent.com/hjnilsson/country-flags/master/png250px/{}.png";

        $http.get('https://raw.githubusercontent.com/lukes/ISO-3166-Countries-with-Regional-Codes/master/slim-2/slim-2.json',
                {cache: true})
                .success(function (data) {
                    angular.forEach(data, function (item) {
                        item.flag = flagUrl.replace("{}", item['alpha-2'].toLowerCase());
                    });

                    deferred.resolve(data);
                }).error(function (data) {
                    growl.warn("Error loading country data");
                    deferred.reject();
                });

        return deferred.promise;

    }]);

2 个答案:

答案 0 :(得分:1)

工厂中的所有东西都会在工厂注入任何控制器后立即运行,这会在您的应用程序被引导时发生。

执行此操作的唯一方法是使用获取数据的方法从工厂返回对象。

angular.module('myModule')
.factory('countrylist', ['$http', 'growl', '$q', function ($http, growl, $q) {
  return {
    fetch: function() {
      var deferred = $q.defer();
      var flagUrl = "https://raw.githubusercontent.com/hjnilsson/country-flags/master/png250px/{}.png";

      $http.get('https://raw.githubusercontent.com/lukes/ISO-3166-Countries-with-Regional-Codes/master/slim-2/slim-2.json',
            {cache: true})
            .success(function (data) {
                angular.forEach(data, function (item) {
                    item.flag = flagUrl.replace("{}", item['alpha-2'].toLowerCase());
                });

                deferred.resolve(data);
            }).error(function (data) {
                growl.warn("Error loading country data");
                deferred.reject();
            });

      return deferred.promise;
    }
  };
}]);

然后在你的控制器中你显然必须这样做

countryList.fetch().then(...)

答案 1 :(得分:1)

让它变得简单。它就像

一样简单
  1. 在您的服务中退回promise(无需在服务中使用then
  2. 在控制器中使用then
  3. 演示。 http://plnkr.co/edit/cbdG5p?p=preview

    var app = angular.module('plunker', []);
    
    app.service('myService', function($http) {
      return {
        async: function() {
          return $http.get('test.json');  //1. this returns promise
        }
      };
    });
    
    app.controller('MainCtrl', function( myService,$scope) {
      myService.async().then(function(d) { //2. so you can use .then()
        $scope.data = d;
      });
    });
    

    这是我的复制/粘贴答案 Processing $http response in service