Force AngularJS service to return data before loading controller

JVG picture JVG · Aug 28, 2013 · Viewed 38.5k times · Source

I have a service in Angular which uses my API to get user information and provides it to my controllers. It's set up like this:

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

In my controllers, I include it like:

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

This is returning no data, while if I put the same service function in the controller itself it returns just fine. What am I missing here? Never used DI/Services in Angular before so might be a simple mistake somewhere.

I need to ensure that the service returns data before the controller loads. How can this be accomplished

Answer

zs2020 picture zs2020 · Aug 28, 2013

You can make the factory to return a promise like this:

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

And in your controller, do

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

This can guarantee that whenever you use the service, it always gives you the data synchronously, you don't have to necessarily load any data before loading the controller.