2013-09-07 28 views
16

EDIT

Pierwsza odpowiedź jest elegancki jeden, ale, jak wspomniano kilka razy w tej kwestii i kolejne pytania na StackOverflow, problemem jest to, że usługa i sterownik uruchomić swoje rzeczy, zanim dane faktycznie dotrą.

(Ostatni komentarz na pierwszej odpowiedzi :)

Tak, problemem jest to, że wywołania API zakończyć po wykonaniu usługi biegnie i wszystko wraca do sterownika, patrz tutaj screencast.com/t/ uRKMZ1IgGpb7 ... To jest moje pytanie BASE, w jaki sposób mogę czekać na wszystkie części, aby dane dotarły?

To tak jak mówię to na powtórzenia, jaki sposób uczynić usługę, która wypełnia tablicę po pomyślnym pobierania danych i kontroler uzyskiwanie danych po to wszystko dzieje, bo jak widać w mój zrzut ekranu, rzeczy działają w innej kolejności.


mam ten kod:

var deferred = $q.defer(); 
      $http.get('../wordpress/api/core/get_category_posts/?category_id=14 ').success(function(data) { 
       //we're emptying the array on every call 
       theData = []; 
       catName = data.category.slug; 
       theData = data; 
       theData.name = catName; 
       aggregatedData.push(theData); 
      }); 
      $http.get('../wordpress/api/core/get_category_posts/?category_id=15 ').success(function(data) { 
       theData = []; 
       catName = data.category.slug; 
       theData = data; 
       theData.name = catName; 
       aggregatedData.push(theData); 
      }); 
      $http.get('../wordpress/api/core/get_category_posts/?category_id=16 ').success(function(data) { 
       theData = []; 
       catName = data.category.slug; 
       theData = data; 
       theData.name = catName; 
       aggregatedData.push(theData); 
      }); 
      $http.get('../wordpress/api/core/get_category_posts/?category_id=17 ').success(function(data) { 
       theData = []; 
       catName = data.category.slug; 
       theData = data; 
       theData.name = catName; 
       aggregatedData.push(theData); 
      }); 
      //deferred.resolve(aggregatedData); 
      $timeout(function() { 
       deferred.resolve(aggregatedData); 
      }, 1000); 
      /*//deferred.reject('There is a connection problem.'); 
      if (myservice._initialized) { 
       $rootScope.$broadcast('postsList', deferred.promise); 
      }*/ 
      //myservice._initialized = true; 
      myservice = deferred.promise; 
      return deferred.promise; 

dla życia mnie nie mogę zrozumieć, dlaczego muszę umieścić limit czasu przy przejściu wynikowy tablicę do odroczenia?

Czy zasada nie powinna brzmieć, odłożyć czekanie na informacje, a następnie zwrócić obietnicę? Jaki jest sens tej 1 sekundy? Z tego, co rozumiem, odroczenie powinno być w stanie czekać tak długo, jak potrzeba, aby API zwróciło wynik i zwróciło obiecane dane.

Jestem naprawdę zdezorientowany, przez ostatnie dwie godziny uderzałem głową o ściany, ponieważ nie otrzymywałem żadnych danych w moim kontrolerze, tylko gdy umieściłem tam ten czas.

+0

Czy chcesz umieścić wszystkie zwracane wartości '$ http.get' w [' $ q.all'] (http://docs.angularjs.org/api/ng.$q)? –

+0

Przerzucam wszystkie wyprowadzone tablice w zbiorczych danych, aby móc przekazać ten obiekt do $ q. Chcę zrozumieć, co tak naprawdę się dzieje, oto jsFiddle, http://jsfiddle.net/tjnWQ/ .... Jak działa tutaj obietnica. –

+0

Szczerze mówiąc, jestem podekscytowany frustracją. Już prawie 6 tygodni staram się opanować ten Angular, naprawdę podoba mi się ten pomysł, rozumiem bity i kawałki, mam 3-4 mini aplikacje działające, ale są pewne dziury w mojej wiedzy o tym kątowym ramy, które staną się przeszkodą w tworzeniu rzeczywistego produktu użytkowego :). Poddałem się i wydałem dużo pieniędzy na tę książkę http://www.packtpub.com/angularjs-web-application- development/book –

Odpowiedz

59

IMHO Myślę, że jest bardzo sprytny (i elegancki) sposób na zrobienie tego z $q.all.

Proszę spojrzeć na kod poniżej.

Zakładam, że chcesz od razu zwrócić dane z wszystkimi wynikami zebranymi na dużej tablicy.

var myApp = angular.module('myApp', []); 

myApp.factory('myService', function ($http, $q) { 
    return { 
     getAllData: function() { 
      return $q.all([ 
       $http.get('../wordpress/api/core/get_category_posts/?category_id=14'), 
       $http.get('../wordpress/api/core/get_category_posts/?category_id=15'), 
       $http.get('../wordpress/api/core/get_category_posts/?category_id=16'), 
       $http.get('../wordpress/api/core/get_category_posts/?category_id=17') 
      ]).then(function (results) { 
       var aggregatedData = []; 
       angular.forEach(results, function (result) { 
        aggregatedData = aggregatedData.concat(result.data); 
       }); 
       return aggregatedData; 
      }); 
     } 
    }; 
}); 

widać powyżej, że aggregatedData jest generowany tylko raz wszystkie połączenia są zakończone asynchroniczny poprzez $q.all.

Wystarczy włączyć usługę jako uzależnienia do jednego z kontrolerów, na przykład, i wezwać serwis jak ten myService.getAllData()

nadzieję, że pomoże lub po prostu daj mi znać, jeśli potrzebujesz pełnego pracy przykład i I może zapewnić jeden! :)

+14

+1 dla '$ q.all', i być nieco bardziej SUCHEGO:' [14, 15, 16, 17] .map (funkcja (id) { return $ http.get ('../ wordpress/api/core/get_category_posts /? category_id = '+ id); }); ' – plalx

+0

tak! Zgadzam się z _plalx_! po prostu nie chciałem go pomylić z jakimś słodkim dodatkowym kodem :) –

+0

NIESAMOWITE! Z pewnością wygląda bardziej elegancko niż moje :). I w odniesieniu do moich bólów głowy powyżej: Należy założyć, że $ q.all będzie czekać na WSZYSTKIE wywołania API, aby zakończyć, a następnie serwować dane w ostatecznej tablicy. Dane, które można również oczekiwać w kontrolerze z .then()? –

11

Połączenia $http.get są asynchroniczne, ale nie czekają, aż wszystkie zostaną zakończone przed rozwiązaniem odroczonego. Tutaj działa z limitem czasu tylko dlatego, że masz szczęście, że połączenia mają czas na zakończenie w ciągu 1 sekundy, jednak nie jest to w ogóle wiarygodne.

Nie będę tu powtarzać kompletnego rozwiązania, ale spójrz na numer my answer, aby uzyskać podobny problem.

+0

Wiem, to dokładnie to, co mówiłem, że timeout to rekwizyt używany w demach, a nie w prawdziwych API. Tego właśnie szukam, sposobu oczekiwania i wyświetlenia danych po obu stronach (Service-> Controller-> View) –

+0

Hej plalx, ​​czy możesz zobaczyć pierwszą odpowiedź i mój komentarz, kod jest bardzo czysty, ale jest problem z timingiem http://screencast.com/t/uRKMZ1IgGpb7 - dane wciąż przychodzą po. –

+0

@ArthurKovacs Czy mógłbyś stworzyć skrzypce z całym odpowiednim kodem? – plalx