2012-09-04 17 views
9

W mojej aplikacji muszę pobrać niektóre dane JSON i przypisać je do tablicy przed załadowaniem strony. To jest mój kod do pobierania JSON korzystania z usługi CardService:Obietnica AngularJS zostaje rozwiązana przed załadowaniem danych.

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

w bloku rozwiązać sterownika, mam następujące:

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

oraz w rzeczywistym sterowniku, mam następujące:

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

Problem polega na tym, że funkcja fetchCards w usłudze wydaje się rozwiązać obietnicę, zanim dane JSON zostaną przypisane do zmiennej karty. To powoduje, że mój widok ładuje się z pustymi danymi, dopóki nie odświeżę się kilka razy i nie będę miał szczęścia.

Potrafię potwierdzić późne wczytanie, jak wtedy, gdy rejestruję zmienną karty w konsoli, otrzymuję pustą tablicę w linii 122 (gdy mój widok jest załadowany) i pełną tablicę w linii 57 (gdy połączenie JSON jest udane). Kod linii 57 jakoś wykonuje po widok jest załadowany.

Jak to naprawić?

Odpowiedz

16

Nie użyłem resolve, ale wyrzucam to na wypadek, gdyby problem, który masz, był związany z powiązaniem z tablicą zwróconą przez usługę.

Jeśli powrocie swoją tablicę cards z usługi i wiązanie się z nim w interfejsie użytkownika może chcesz spróbować, aby wypełnić tę samą tablicę zamiast ustawiania cards = data; (które zastąpią lokalne karty z nowej tablicy, która nie jest związana do interfejsu użytkownika).

Coś jak:

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

Zobacz this fiddle na przykład pracy, co staram się opisać. Kilkakrotne kliknięcie pierwszego przycisku zaktualizuje widok, ale po kliknięciu drugiego przycisku wiązanie zostanie zerwane.

Główną różnicą między nimi jest:

  1. Pierwszy przycisk używa data.length = 0 i data.push() zachować referencyjne oryginalnej tablicy za
  2. Drugi przycisk nadpisuje oryginalnego data odniesienie tablicę z nową używając data = newArray

Aktualizacja: Ponadto, jak Mark Rajcok, wymienionej poniżej można użyć angular.copy zachować odniesienie oryginalnej tablicy poprzez opróżnienie go i dodając nowe od źródła jak to:

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

Nie jestem gejem, ale mogę cię pocałować teraz!!! To rozwiązało wszystko. Dzięki za mil! – kshep92

+0

Jeśli chodzi o problem z renderowaniem widoku przed załadowaniem danych, zdałem sobie sprawę, że problem polegał na tym, że obietnica została zadeklarowana i rozwiązana/odrzucona. Spójrz na to skrzypce: http://jsfiddle.net/kshep92/stdwj/3/ – kshep92

+5

'angular.copy (dane, karty)' również będzie działać. Kiedy cel zostanie dostarczony do [copy()] (http: // docs.angularjs.org/api/angular.copy), najpierw usunie elementy miejsca docelowego, a następnie skopiuje je ze źródła. –

Powiązane problemy