web-dev-qa-db-fra.com

Forcer le service AngularJS à renvoyer les données avant de charger le contrôleur

J'ai un service dans Angular qui utilise mon API pour obtenir des informations utilisateur et les fournit à mes contrôleurs. C'est mis en place comme ça:

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

Dans mes contrôleurs, je l’inclus comme:

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

Cela ne renvoie aucune donnée, alors que si je mets la même fonction de service dans le contrôleur, elle retourne très bien. Qu'est-ce que j'oublie ici? Jamais utilisé DI/Services dans Angular auparavant, cela pourrait donc être une simple erreur quelque part.

Je dois m'assurer que le service renvoie les donnéesavantle contrôleur se charge. Comment cela peut-il être accompli

34
JVG

Vous pouvez faire l'usine pour retourner une promesse comme ceci:

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

Et dans votre contrôleur, faites

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

Cela peut garantir que chaque fois que vous utilisez le service, il vous donne toujours les données de manière synchrone , vous ne devez pas nécessairement charger de données avant de charger le contrôleur.

42
zsong

Votre service userInfo doit renvoyer la promesse retournée par $http. Cette promesse sera ensuite injectée dans votre contrôleur et la vue sera mise à jour dès que la promesse sera résolue.


Si vous ne souhaitez pas que la vue soit rendue avant la résolution de userInfo, vous devez définir une propriété resolve sur votre route et y injecter votre service:

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

Ensuite, injectez simplement userInfoData dans votre contrôleur à la place du service userInfo.

17
Joseph Silber

J'ai rencontré le même problème dans lequel je devais charger des données dans un service en utilisant $ resource et obtenir ces données dans les contrôleurs $ scope . Je ne voulais pas retourner directement la promesse et ensuite utiliser un résolveur dans le contrôleur (@zsong a écrit) mais pour faire toute la magie dans le service une fois et utiliser la possibilité d'attribuer une promesse directement à un $ scope comme le souligne @Joseph Silber, voici ce que j'ai fait:

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

Et utilisé dans le contrôleur comme ceci:

userInfo($scope);

Pas beaucoup d'amélioration mais cela m'a permis une syntaxe plus claire dans mes contrôleurs, j'espère que ça va aider même trois ans plus tard!

0
PaulCo

Vous pouvez affecter l'objet de ressource à votre variable de la manière suivante:

0
Ahmed Alsharkawy