La promesse AngularJS est résolue avant que les données ne soient chargées

Dans mon application, je dois récupérer des données JSON et l'affecter à un tableau avant la chargement de la page. C'est mon code pour récupérer le JSON en utilisant le service CardService:

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; }; ... } 

Dans le bloc de résolution du contrôleur, j'ai le suivant:

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

Et dans le contrôleur actuel, j'ai le suivant:

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

Le problème est que la fonction fetchCards dans le service semble résoudre la promesse avant que les données JSON ne soient affectées à la variable des cartes. Cela mène à mon affichage avec des données vierges jusqu'à ce que je me rafraîchisse quelques fois et que j'ai de la chance.

Je peux confirmer le chargement tardif comme lorsque je connecte la variable de carte dans la console, j'obtiens un tableau vide à la ligne 122 (lorsque ma vue est chargée) et un tableau complet à la ligne 57 (lorsque l'appel JSON est réussi). Le code de la ligne 57 s'effectue d'une manière ou d'une autre après la chargement de la vue.

Comment puis-je réparer ça?

Je n'ai pas utilisé la resolve mais je lance cela ici, au cas où le problème que vous rencontrez est lié à la liaison à un tableau renvoyé d'un service.

Si vous renvoyez votre gamme de cards d'un service et vous liez dans l'interface utilisateur, vous pouvez essayer de remplir ce même tableau au lieu de définir des cards = data; (Qui remplacera les cartes locales par un nouveau tableau qui n'est pas lié à l'interface utilisateur).

Quelque chose comme:

 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; }, 

Voir ce violon pour un exemple utile de ce que j'essaie de décrire. En cliquant sur le premier bouton plusieurs fois, vous mettez à jour la vue, mais une fois que vous cliquez sur le deuxième bouton, la liaison sera interrompue.

La principale différence entre les deux est:

  1. Le premier bouton utilise data.length = 0 et data.push() pour conserver la référence du tableau d'origine
  2. Le deuxième bouton remplace la référence du tableau de data origine par une nouvelle utilisant data = newArray

Mise à jour: De plus, comme Mark Rajcok, mentionné ci-dessous, vous pouvez utiliser angular.copy pour conserver la référence du tableau d'origine en le vidant et en ajoutant de nouveaux sources de la source comme ceci:

 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; },