AngularJS承诺在加载数据之前得到解决

时间:2012-09-04 14:24:41

标签: javascript ajax angularjs

在我的应用程序中,我必须获取一些JSON数据并在加载页面之前将其分配给数组。这是我使用CardService服务获取JSON的代码:

cards = [];

var cs = {
...
fetchCards: function() {
      var d = $q.defer();
      $http.get("data/cards.php").success(function(data) {
                      cards = data;
                      d.resolve();
                }).error(function(data, status) {
                      d.reject(status);        
                 });
               return d.promise;
      },
getCards: function() { return cards; };
...
}

在控制器的解析块中,我有以下内容:

WalletController.resolve = {
        getCards: function(CardService) {
                CardService.fetchCards().then(loadView, showError);
        }
}

在实际控制器中,我有以下内容:

function WalletController($scope, CardService) {
    $scope.cards = CardService.getCards();
}

问题是,服务中的fetchCards函数似乎在将JSON数据分配给cards变量之前解析了promise。这导致我的视​​图加载空白数据,直到我刷新几次并获得幸运。

我可以确认延迟加载,因为当我在控制台中记录卡片变量时,我在第122行(当我的视图加载时)获得一个空数组,在第57行获得一个完整数组(当JSON调用成功时) 。 加载视图后,第57行代码以某种方式执行

我该如何解决这个问题?

1 个答案:

答案 0 :(得分:16)

我没有使用过resolve但是我把它扔到那里以防你遇到的问题与绑定到服务返回的数组有关。

如果要从服务中返回cards数组并在UI中绑定它,您可能希望尝试填充相同的数组而不是设置cards = data;(这将覆盖本地卡一个未绑定到UI的新数组。)

类似的东西:

fetchCards: function() {
      var d = $q.defer();
      $http.get("data/cards.php").success(function(data) {
                      cards.length = 0;
                      for(var i = 0; i < data.length; i++){
                          cards.push(data[i]);
                      }
                      d.resolve();
                }).error(function(data, status) {
                      d.reject(status);        
                 });
               return d.promise;
      },

请参阅this fiddle,了解我正在尝试描述的实例。多次单击第一个按钮将更新视图,但是一旦单击第二个按钮,绑定将被破坏。

两者之间的主要区别是:

  1. 第一个按钮使用data.length = 0data.push()来保留原始数组的引用
  2. 第二个按钮使用data
  3. 覆盖原始data = newArray数组引用

    更新另外,正如Mark Rajcok所提到的,你可以使用angular.copy来保留原始数组的引用,将其清空并从源代码中添加新的数组:

    fetchCards: function() {
          var d = $q.defer();
          $http.get("data/cards.php").success(function(data) {
                          angular.copy(data, cards);
                          d.resolve();
                    }).error(function(data, status) {
                          d.reject(status);        
                     });
                   return d.promise;
          },