Search code examples
javascriptangularjsasynchronousangularjs-scopeangularjs-service

How to asynchronously populate a $scope variable in AngularJS?


I have the following service:

app.service('Library', ['$http', function($http) {

    this.fonts = [];
    this.families = [];

    // ... some common CRUD functions here ...

    // Returns the font list
    this.getFonts = function() {
        if(_.isEmpty(this.fonts)) this.updateFonts();
        return this.fonts;
    };

    // Returns the family list
    this.getFamilies = function() {
        if(_.isEmpty(this.families)) this.updateFamilies();
        return this.families;
    };

    // Update the font list
    this.updateFonts = function() {
        var self = this;
        $http.get(BACKEND_URL+'/fonts').success(function(data) {
            self.fonts = data;
            console.log('Library:: fonts updated', self.fonts);
        });
    };

    // Update the family
    this.updateFamilies = function() {
        var self = this;
        $http.get(BACKEND_URL+'/families').success(function(data) {
            var sorted = _.sortBy(data, function(item) { return item });
            self.families = sorted;
            console.log('Library:: families updated', self.families);
        });
    };
}]);

And the following main controller code:

app.controller('MainController', ['$scope', '$state', 'Cart', 'Library', function($scope, $state, Cart, Library) {
    console.log('-> MainController');

    // Serve the right font list depending on the page
    $scope.fonts = $state.is('home.cart') ? Cart.getFonts() : Library.getFonts();
    $scope.families = Library.getFamilies();

}]);

The problem is, that when the view requests the content of $scope.fonts, it's still empty.

How to update $scope.fonts and $scope.families when the loading is over?

I could use $scope.$watch but I'm sure there is a cleaner way to do it...


Solution

  • Thanks for all the answers! I ended up using a mix of callback and promise, as follow:

    app.service('Library', function($http) {
    
        // Returns the font list
        this.getFonts = function(callback) {
            if(_.isEmpty(self.fonts)) return self.updateFonts(callback);
            else return callback(self.fonts);
        };
    
        // Update the font list
        this.updateFonts = function(callback) {
            return $http.get(BACKEND_URL+'/fonts').success(function(data) {
                self.fonts = data;
                callback(data);
            });
        };
    });
    

    And, in the controller:

    app.controller('MainController', function(Library) {
        Library.getFonts(function(fonts) { $scope.fonts = fonts });
    });
    

    I tried all your suggestions, but this is the best one working with the rest of my code.