8

I am new to AngularJS and have a service that loads my initial user configuration

angular.module('myApp').service('myService', ['$http', function ($http) {
    var self = this;
    self.user = {};

    self.loadConfiguration = function () {
        $http.get('/UserConfig').then(function (result) {
            self.user = result.data;
        });
    };

    self.loadConfiguration();
}]);

I have a controller that uses the configuration from this service

angular.module('myApp').controller('myController', ['$scope', 'myService', function ($scope, myService) {
    var self = this;

    // calculation based on service value
    self.something = myService.user.something * something else;
}]);

The problem here is that myService.user.something may be undefined since the AJAX request may not have completed when this code is called. Is there a way to have the service complete before any other code is run? I want the service function 'loadConfiguration' to be run only once irrespective of the number of controllers that depend on it.

2 Answers 2

6

You can call your service method inside .run() function

Run Blocks

Run blocks are the closest thing in Angular to the main method. A run block is the code which needs to run to kickstart the application. It is executed after all of the service have been configured and the injector has been created. Run blocks typically contain code which is hard to unit-test, and for this reason should be declared in isolated modules, so that they can be ignored in the unit-tests.

https://docs.angularjs.org/guide/module

angular.module('myApp').run(function()){
   //use your service here
}

One way to deal with ajax delay, is use $rootScope.$broadcast() function on $http.success which will broadcast your custom event to all controllers. Antoher way is to use promises and perform actions in controllers after resolve. Here are some ideas: https://groups.google.com/forum/#!topic/angular/qagzXXhS_VI/discussion

Sign up to request clarification or add additional context in comments.

1 Comment

Best Choice! ^^ Thank You for the help:)
5

If you want to make sure that your code in controller gets executed after your AJAX call returns, you may use events.

Use this in your service:

angular.module('myApp').service('myService', ['$http', '$rootScope', function ($http, $rootScope) {
    var self = this;
    self.user = {};

    self.loadConfiguration = function () {
        $http.get('/UserConfig').then(function (result) {
            self.user = result.data;
            $rootScope.$broadcast('myService:getUserConfigSuccess');
        });
    };

    self.loadConfiguration();
}]);

In your controller:

angular.module('myApp').controller('myController', ['$scope', 'myService', function ($scope, myService) {
    var self = this;

    $scope.$on('myService:getUserConfigSuccess', function() {
        // calculation based on service value
        self.something = myService.user.something * something else;
    })
}]);

You can even attach an object to the event.

Please refer to https://docs.angularjs.org/api/ng/type/$rootScope.Scope .

5 Comments

Your answer mostly works. It does not work if the service has already loaded before the controller is initialized because then the $scope.$on('myService:getUserConfigSuccess') will never fire.
@user1 Ahhhh, yes! So if you wanna make sure, you can either call loadConfiguration() from your controller, or add a check of if user already loaded in the controller (if yes, use it; if no, add a event listener).
Yes, that is what I ended up doing. :) I wanted to leave a record of the accepted answer's shortcoming to help out anyone reading this several months from now.
I liked this solution actually of the two i came across you can check this solution too .. stackoverflow.com/questions/29475825/… ... But in this scenario now i have around 50 controllers, all controller need some data from the function that runs at service level ,, am i expected to wrap all my controller block in side the event handler :( Is there any alternative..
@BlackBurn027 You may have a look at rxjs github.com/Reactive-Extensions/RxJS

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.