2013-08-28 11 views
33

Mam usługę w Angular, która używa mojego interfejsu API, aby uzyskać informacje o użytkowniku i udostępnia je moim kontrolerom. To skonfigurować tak:Wymuszenie usługi AngularJS w celu zwrócenia danych przed załadowaniem kontrolera

angular.module('myApp', ['myApp.filters', 'myApp.services', 'myApp.directives', 'ngResource', 'infinite-scroll', 'ui.bootstrap', 'ngCookies', 'seo']) 
    .service('userInfo', function($http, $cookies){ 
    $http.get('/api/users/' + $cookies.id). 
    success(function(data) { 
     var userInfo = data.user[0]; 

     return userInfo; 
    }); 
    }). // other stuff comes after this 

W moich kontrolerów, ja to nie podoba:

function userProfile($scope, $cookies, userInfo, $http, $resource, $routeParams, $rootScope){ 
    $scope.user = userInfo; 
    console.log('user info is') 
    console.log(userInfo); 

Ten wraca żadnych danych, a jeśli mogę umieścić taką samą funkcję serwisową w samym kontrolerze zwraca tylko w porządku. Czego tu mi brakuje? Nigdy nie używano DI/usług w Angular, więc może to być zwykły błąd.

Muszę się upewnić, że usługa zwraca dane przed sterownika ładuje. W jaki sposób można to osiągnąć?

+6

można uprościć konsolę.logs w ten sposób: 'console.log (" informacja użytkownika jest ", userInfo);' –

+0

@EddieMongeJr naprawdę? nie miałem pojęcia, dzięki. – Jascination

Odpowiedz

42

Można dokonać fabryka wrócić obietnicę takiego:

angular.module('myApp', ['myApp.filters', 'myApp.services', 'myApp.directives', 'ngResource', 'infinite-scroll', 'ui.bootstrap', 'ngCookies', 'seo']) 
    .service('userInfo', function ($http, $cookies) { 
    var promise = $http.get('/api/users/' + $cookies.id). 
    success(function (data) { 
     var userInfo = data.user[0]; 
     return userInfo; 
    }); 
    return promise; 
}) // other stuff comes after this 

aw kontrolerze, zrobić

function userProfile($scope, $cookies, userInfo, $http, $resource, $routeParams, $rootScope){ 
    userInfo.then(function(data){ 
     $scope.user = data; 
    }); 
} 

To może zagwarantować, że gdy korzystasz z usługi, to zawsze daje dane są synchroniczne, nie trzeba koniecznie ładować żadnych danych przed załadowaniem kontrolera.

+6

Obietnice można przypisać bezpośrednio do '$ scope'. Kiedy obietnica ustąpi, Angular automatycznie aktualizuje widok. –

+0

To działa. Twoje zdrowie. – Jascination

+6

Należy pamiętać, że obietnice nie są automatycznie rozpakowywane w kanciarze 1.2+. –

17

Twój serwis userInfo musi zwrócić obietnicę zwróconą przez $http. Ta obietnica zostanie następnie wprowadzona do kontrolera, a widok zostanie zaktualizowany, gdy tylko obietnica się powiedzie.


Jeśli nie chcesz, aby być renderowane w ogóle przed userInfo ustąpieniu, należy ustawić właściwość resolve na trasie i wstrzyknąć swoje usługi tam:

$routeProvider.when('/profile', { 
    templateUrl: 'profile', 
    controller: userProfile, 
    resolve: { 
     userInfoData: function ($q, userInfo) { 
      return userInfo; 
     } 
    } 
}); 

Następnie wystarczy wstrzyknąć userInfoData do kontrolera zamiast usługi userInfo.

+1

Potrzebuję tych danych do wszystkich kontrolerów/tras, czy istnieje szczególny sposób, aby wstrzyknąć je raz, więc nie muszę tego robić ponad 20 razy na każdą trasę? – Jascination

+0

@Jascination - Nie o tym wiem. Myślę, że po prostu ustawisz 'resolve: resolveUserInfo' dla wszystkich tras, których potrzebujesz. –

+0

Interesujące. Próbowałem Twojego rozwiązania, ale nadal robi to samo - ładowanie kontrolera przed usunięciem danych. Wiem, że to prawdopodobnie nie powinno być z powodu "rozwiązania", zakładam, że jest to problem asynchroniczny/wywołania zwrotnego, ponieważ funkcja 'resolveUserInfo' nie kończy ładowania danych przed powrotem. – Jascination

0

można przypisać obiekt do zmiennej zasobów jak tego powrotnej $ http.get (URL)

0

Mam wobec tego samego problemu, w którym miałem do załadowania danych do serwisu za pomocą $ zasobu i uzyskać dane do kontrolerów $ scope. Nie chciałem bezpośrednio zwrócić obietnicy, a następnie użyć resolwera w kontrolerze (jak napisał @zsong), ale raz wykonać całą magię w serwisie i użyć możliwości przypisania obietnicy bezpośrednio do $ scope jako @ Joseph Silber podkreślić, więc o to, co zrobiłem:

return function($scope){promise.then(function(data){$scope.user = data})}; 

i wykorzystał je w sterowniku jak ten:

userInfo($scope); 

Niewiele poprawy, ale to pozwoliło mi wyraźniejszy składni w moich kontrolerami , mam nadzieję, że pomoże to nawet trzy lata później!