2015-02-08 16 views
5

Jestem nowy w angularjs. Mój cel jest bardzo prosty. Chcę wykonać wywołanie ajax, aby uzyskać dane, a po zakończeniu chcę wykonać drugie wywołanie, aby uzyskać inny zestaw danych, który jest zależny od informacji z pierwszego zestawu.

Próbuję zrobić to wykorzystując mechanizmy obietnic, dzięki czemu mogę wykorzystać łańcuchy zamiast zagnieżdżonych wywołań ajaxowych i lepiej zachować zdolność do posiadania niezależnych funkcji, które mogę powiązać w razie potrzeby.

Mój kod podobny do następującego:

var promiseGetWorkTypes = function ($q, $scope, $http) { 
 
\t console.log("promiseGetWorkTypes"); 
 

 
\t return $q(function (resolve, reject) { 
 
\t \t $http({ 
 
\t \t \t method: 'GET', 
 
\t \t \t url: '/WorkTypes' 
 
\t \t }).then(
 
\t \t \t function (payload) { 
 
\t \t \t \t console.log("Got workttypegroups") 
 
\t \t \t \t console.log(payload); 
 

 
\t \t \t \t $scope.WorkTypeGroups = payload.data; 
 

 
\t \t \t \t console.log("End of worktypegroups"); 
 
\t \t \t \t resolve(payload); 
 
\t \t \t }, 
 
\t \t \t function (payload) { 
 
\t \t \t \t reject(payload); 
 
\t \t \t }); 
 
\t }); 
 
}; 
 

 
var promiseGetRecentActivities = function ($q, $scope, $http) { 
 
\t console.log("promiseGetRecentActivities"); 
 

 
\t return $q(function (resolve, reject) { 
 
\t \t $http({ 
 
\t \t \t method: 'GET', 
 
\t \t \t url: '/RecentHistory' 
 
\t \t }).then(
 
\t \t \t function (payload) { 
 
\t \t \t \t $scope.RecentActivities = payload.data; 
 

 
\t \t \t \t resolve(payload); 
 
\t \t \t }, 
 
\t \t \t // data contains the response 
 
\t \t \t // status is the HTTP status 
 
\t \t \t // headers is the header getter function 
 
\t \t \t // config is the object that was used to create the HTTP request 
 
\t \t \t function (payload) { 
 
\t \t \t \t reject(payload); 
 
\t \t \t }); 
 
\t }); 
 
}; 
 

 
var index = angular.module("index", []); 
 

 
index 
 
.controller('EntitiesController', function ($scope, $http, $timeout, $q) { 
 
\t promiseGetWorkTypes($q, $http, $scope) 
 
\t \t .then(promiseGetRecentActivities($q, $http, $scope)); 
 
}

Jednak kiedy patrzę na mojego konsoli debugowania, widzę, że wezwanie do „promiseGetRecentActivities” rozpoczyna się przed wywołaniem Przeładunek Ajax wystąpił dla "promiseGetWorkTypes".

Czego tu brakuje lub robię źle?

+1

użyj '$ q.all' http://jsfiddle.net/ThomasBurleson/QqKuk/ – underscore

+0

Nie, nie' $ q.all() '. OP chce dokonać dwóch wywołań ajax w serii. –

+3

http://stackoverflow.com/questions/23803743/what-is-the-deferred-antipattern-and-how-do-i-avoid-it –

Odpowiedz

6

Kiedy piszesz

promiseGetWorkTypes($q, $http, $scope).then(promiseGetRecentActivities($q, $http, $scope)); 

promiseGetActivites jest nazywany w tym czasie ta linia jest uwzględniany. Powinieneś być w stanie owinąć wezwanie do promiseGetActivities w innej funkcji, aby opóźnić połączenia, dopóki pierwsza obietnica została rozwiązana w celu uzyskania połączenia, aby uruchomić w kolejności:

promiseGetWorkTypes($q, $http, $scope).then(function() { 
    promiseGetRecentActivities($q, $http, $scope); 
}); 

Powodem nie jest nic wspólnego z tym, co się dzieje wewnątrz then, ale ze względu na składnię Javascript. Poniższy:

myFunc1(myFunc2()); 

przechodzi do myFunc1 wynikiem wywołania myFunc2(), a nie odniesienie do funkcji myFunc2. Logicznie rzecz biorąc, myFunc2 musiałoby zostać uruchomione przed myFunc1. Jeśli napisałeś

myFunc1(myFunc2); 

następnie myFunc1 otrzyma odniesienie do myFunc2 i tak myFunc1 byłoby przed myFunc2 (aw rzeczywistości myFunc2 będzie działać tylko wtedy, gdy gdzieś wewnątrz myFunc1 jest kod, który nazywa).

Definiowanie funkcji wbudowanej/anonimowo nie zmienia tego zachowania. Aby przejść wyniku anonimowej funkcji do innej funkcji można wykonać następujące czynności

myFunc1((function() { 
    return 'something'; 
})()); 

który najpierw ocenić funkcję anonimową, a jego wartości zwracanej, 'something' zostaną przekazane do myFunc1. Przekazać odwołanie do anonimowej funkcji można wykonać następujące czynności:

myFunc1(function() { 
    return 'something'; 
}); 

i wtedy będzie do myFunc1 czy będzie kiedykolwiek nazywamy funkcję przekazaną do niej.

przenosząc je z powrotem na swoje pytanie, kod:

promiseGetWorkTypes($q, $http, $scope).then(promiseGetRecentActivities($q, $http, $scope)); 

przechodzi wynik promiseGetRecentActivities($q, $http, $scope) do then, więc musi działać przed then jest uruchamiany, a więc na pewno nie czekać na obietnicy promiseGetWorkTypes do rozstrzygnięcia. Co wydaje się chce to przekazać mu funkcję, kiedy nazywa, kursujący promiseGetRecentActivities($q, $http, $scope), która jest co

promiseGetWorkTypes($q, $http, $scope).then(function() { 
    promiseGetRecentActivities($q, $http, $scope); 
}); 

robi.

Na marginesie, wydaje się nieco niezwykłe/zbyt skomplikowane przekazywanie $q, $http itd do różnych funkcji, ale myślę, że prawdopodobnie wykraczam poza zakres tego pytania, aby przejść przez alternatywy.

+0

Wow! Wydaje się, że zadziałało, ale nie mogę zrozumieć, dlaczego. Mógłbym pomyśleć, że wywołanie ".then" wstrzymałoby się od wywołania, niezależnie od tego, jaka zmienna funkcyjna została przekazana, dopóki poprzednia obietnica nie zostanie rozwiązana. A jeśli od razu nazywa się "promiseGetRecentActivities", dlaczego nie od razu zadzwoni do anonimowej funkcji? Czy istnieje jakaś logika, która szuka metody bez parametrów lub nienazwanej w wywołaniu ".then"? – dshockey

+0

@dshockey Dodałem więcej do mojej odpowiedzi, aby spróbować wyjaśnić –

+0

To wszystko ma sens i powinienem był sobie uświadomić, że to robię. Sądzę, że zgubiłem się w myśleniu o funkcjach jako pierwszorzędnych przedmiotach i nie zauważyłem, że dzwoniłem do funkcji i przekazywałem wynik, tak jak w przypadku każdego innego języka. DZIĘKUJEMY za wyjaśnienie tego. Pozostało mi tylko jedno pytanie: dlaczego ".then" zezwala na coś innego niż odwołanie do funkcji? Co zrobiłby z innymi danymi? Jestem zaskoczony, że nie wystąpił błąd w czasie wykonywania od próby przekazania wyniku mojego połączenia do "promseGetRecentActivities" zamiast odwołania do funkcji. – dshockey

Powiązane problemy