【问题标题】:AngularJS promise is resolved before data is loadedAngularJS 承诺在数据加载之前解决
【发布时间】:2013-02-03 15:59:40
【问题描述】:

在我的应用程序中,我必须在页面加载之前获取一些 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 数据分配给卡变量之前解决了承诺。这导致我的视​​图加载空白数据,直到我刷新几次并幸运。

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

我该如何解决这个问题?

【问题讨论】:

    标签: javascript ajax angularjs


    【解决方案1】:

    我没有使用过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 = newArray 用一个新的数组引用覆盖原来的data 数组引用

    更新:另外,正如下面提到的 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;
          },
    

    【讨论】:

    • 我不是同性恋,但我现在可以吻你!!!这解决了一切。谢谢一百万!
    • 关于数据加载前的视图渲染问题,我意识到问题出在声明和解决/拒绝的地方。看看这个小提琴:jsfiddle.net/kshep92/stdwj/3
    • angular.copy(data, cards) 也可以。当一个目的地被提供给copy() 方法时,它将首先删除目的地的元素,然后从源中复制新的元素。
    • 谢谢马克我已经更新了答案以包括angular.copy我以前没用过那个!
    猜你喜欢
    • 2015-06-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-13
    • 2021-08-11
    • 2013-12-31
    相关资源
    最近更新 更多