Oto Plunk, który robi, co chcesz: http://plnkr.co/edit/TTlbSv?p=preview
Chodzi o to, że pracujesz bezpośrednio z obietnicami i ich funkcjami „wtedy”, aby manipulować i uzyskiwać dostęp do asynchronicznie zwróconych odpowiedzi.
app.factory('myService', function($http) {
var myService = {
async: function() {
// $http returns a promise, which has a then function, which also returns a promise
var promise = $http.get('test.json').then(function (response) {
// The then function here is an opportunity to modify the response
console.log(response);
// The return value gets picked up by the then in the controller.
return response.data;
});
// Return the promise to the controller
return promise;
}
};
return myService;
});
app.controller('MainCtrl', function( myService,$scope) {
// Call the async method and then do stuff with what is returned inside our own then function
myService.async().then(function(d) {
$scope.data = d;
});
});
Oto nieco bardziej skomplikowana wersja, która buforuje żądanie, więc możesz je wykonać tylko za pierwszym razem ( http://plnkr.co/edit/2yH1F4IMZlMS8QsV9rHv?p=preview ):
app.factory('myService', function($http) {
var promise;
var myService = {
async: function() {
if ( !promise ) {
// $http returns a promise, which has a then function, which also returns a promise
promise = $http.get('test.json').then(function (response) {
// The then function here is an opportunity to modify the response
console.log(response);
// The return value gets picked up by the then in the controller.
return response.data;
});
}
// Return the promise to the controller
return promise;
}
};
return myService;
});
app.controller('MainCtrl', function( myService,$scope) {
$scope.clearData = function() {
$scope.data = {};
};
$scope.getData = function() {
// Call the async method and then do stuff with what is returned inside our own then function
myService.async().then(function(d) {
$scope.data = d;
});
};
});
then
?myService.async()
wielokrotnie z różnych kontrolerów, w jaki sposób zorganizujesz usługę tak, aby działała tylko$http.get()
dla pierwszego żądania, a wszystkie kolejne żądania tylko zwracają lokalną tablicę obiektów, która jest ustawiana przy pierwszym wywołaniu domyService.async()
. Innymi słowy, chcę uniknąć wielu niepotrzebnych żądań do usługi JSON, kiedy tak naprawdę muszę tylko jedno.$scope.data = myService.async()
bezpośrednio w kontrolerze.Niech to będzie proste. To jest tak proste jak
promise
w usłudze (nie musisz korzystaćthen
z usługi)then
w swoim kontrolerzePróbny. http://plnkr.co/edit/cbdG5p?p=preview
źródło
app.factory
, a w twoim kodzie jestapp.service
. Tak powinno byćapp.factory
w tym przypadku.Ponieważ jest asynchroniczny,
$scope
pobiera dane przed zakończeniem wywołania ajax.Możesz użyć
$q
w swojej usłudze, aby utworzyćpromise
i zwrócić go kontrolerowi, a kontroler uzyska wynik w ramachthen()
połączenia przeciwkopromise
.W twoich usługach
Następnie w kontrolerze:
źródło
this.async = function() {
ithis.getData = function() {return data}
? Mam nadzieję, że rozumiesz, o co mi chodzideffered = $q.defer()
wewnątrz myService.async, jeśli chcę wywołać myService.async () dwa lub więcej razy$q.defer
ponieważ$http
usługa już zwraca obietnicę. Zwrócona obietnica zawiesi się, jeśli$http
zwróci błąd. Ponadto metody.success
i.error
są przestarzałe i zostały usunięte z AngularJS 1.6 .tosh shimayama ma rozwiązanie, ale możesz dużo uprościć, jeśli wykorzystasz fakt, że $ http zwraca obietnice i że obietnice mogą zwrócić wartość:
Mała demonstracja w coffeescript: http://plunker.no.de/edit/ksnErx?live=preview
Twój plunker zaktualizowany moją metodą: http://plnkr.co/edit/mwSZGK?p=preview
źródło
Myślę, że o wiele lepszym sposobem byłoby coś takiego:
Usługa:
A w kontrolerze możesz po prostu użyć:
Angular automatycznie umieści rozdzielczość
awesomeFruits
w$scope.fruits
.źródło
Miałem ten sam problem, ale kiedy surfowałem po Internecie, zrozumiałem, że $ http domyślnie zwraca obietnicę, a potem mogę użyć jej z „wtedy” po zwróceniu „danych”. spójrz na kod:
źródło
W przypadku powiązania interfejsu użytkownika z tablicą należy upewnić się, że zaktualizowano tę samą tablicę bezpośrednio, ustawiając długość na 0 i przekazując dane do tablicy.
Zamiast tego (który ustawia inne odwołanie do tablicy, o
data
którym twój interfejs użytkownika nie będzie wiedział):Spróbuj tego:
Oto skrzypce, które pokazują różnicę między ustawieniem nowej tablicy a opróżnieniem i dodaniem do istniejącej. Nie mogłem uruchomić twojego plnkr, ale mam nadzieję, że to zadziała dla ciebie!
źródło
angular.copy(d, data)
będzie również działać. Gdy miejsce docelowe zostanie dostarczone do metody copy (), najpierw usunie elementy miejsca docelowego, a następnie skopiuje nowe ze źródła.W związku z tym przeszedłem podobny problem, ale nie z pobieraniem lub wysyłaniem przez Angular, ale z rozszerzeniem wykonanym przez inną firmę (w moim przypadku rozszerzenie Chrome).
Problem, z którym się spotkałem, polega na tym, że rozszerzenie Chrome nie powróci,
then()
więc nie mogłem tego zrobić w powyższym rozwiązaniu, ale wynik jest nadal asynchroniczny.Więc moim rozwiązaniem jest stworzenie usługi i przejście do oddzwaniania
Potem w moim kontrolerze
Mam nadzieję, że pomoże to innym uzyskać ten sam problem.
źródło
Przeczytałem http://markdalgleish.com/2013/06/using-promises-in-angularjs-views/ [AngularJS pozwala nam usprawnić logikę naszego kontrolera, składając obietnicę bezpośrednio na zakresie, a nie ręcznie przekazując rozwiązane wartość w wywołaniu zwrotnym sukcesu.]
tak prosto i poręcznie :)
Mam nadzieję, że to pomoże
źródło
defrred.promise
nie jest funkcją.$scope.items = Data.getData();
jest przestarzała w AnglularNaprawdę nie podoba mi się fakt, że z powodu „obiecującego” sposobu robienia rzeczy konsument usługi korzystającej z $ http musi „wiedzieć”, jak rozpakować odpowiedź.
Chcę tylko zadzwonić i pobrać dane, podobnie jak w starym
$scope.items = Data.getData();
sposobie, który jest już przestarzały .Próbowałem przez chwilę i nie znalazłem idealnego rozwiązania, ale oto mój najlepszy strzał ( Plunker ). Może być komuś przydatny.
Następnie kontroler:
Są wady, które już dostrzegam
getData
może zaakceptowaćobj
parametr tylko w postaci obiektu (chociaż może również zaakceptować tablicę), co nie będzie problemem dla wielu aplikacji, ale jest to bolesne ograniczenie$scope.data
z= {}
aby uczynić go przedmiotem (w zasadzie to, co$scope.clearData()
robi powyżej), lub= []
na tablicy, czy to nie będzie działać (mamy już konieczności zakładają coś o jakie dane nadchodzi). Próbowałem wykonać ten krok przygotowawczy INgetData
, ale bez powodzenia.Niemniej jednak zapewnia wzorzec, który usuwa płytę kontrolną „obiecaj rozpakuj” i może być przydatny w przypadkach, gdy chcesz użyć pewnych danych uzyskanych z $ http w więcej niż jednym miejscu, zachowując jednocześnie SUCHOŚĆ.
źródło
Jeśli chodzi o buforowanie odpowiedzi w usłudze, oto kolejna wersja, która wydaje się bardziej prosta niż to, co widziałem do tej pory:
ta usługa zwróci buforowane dane lub
$http.get
;źródło
Wypróbuj poniższy kod
źródło