How to wait for a promise in a Run block in AngularJS?

All we need is an easy explanation of the problem, so here it is.

I really need some data to be loaded before bootstrapping angular. For this reason I’ve created a run block/ Within this run block I call a method on a service which load some data from the server. Since this is a async call, JavaScript gets further with execution, which results in some undefined objects in my app.

I am working with routes, but it is not an option to work with the resolve property.

Could someone provide a solution on how to wait for a promise to be ready in the run block?

EDIT:

Thanks to the given answers, I have solved it by manually bootstrapping angular:

$(document).ready(function () {
    $.ajax('/Data/GetDropdownData', {type:'POST'}).done(function (response) {
        app.run(['ListService',  function (ListService) {
            ListService.setData(response);
        }])

        angular.bootstrap(document, ["sma"]);
    })
})

How to solve :

I know you bored from this bug, So we are here to help you! Take a deep breath and look at the explanation of your problem. We have many solutions to this problem, But we recommend you to use the first method because it is tested & true method that will 100% work for you.

Method 1

You may want to look at this SO question – it shows how to initialize an AngularJS service with asynchronous data.

Here is a plunkr example from that question showing the use of AngularJS services like $http to load the configuration and then do further initialization.

This answer has a great explanation and shows an example of waiting for the DOM to load like this (plunkr example from that answer is here) :

angular.element(document).ready(function() {
  angular.bootstrap(document);
});

Method 2

As I commented would put it here

You may try manual bootstrap

<script> 
   angular.element(document).ready(function() {
      angular.bootstrap(document); 
   });
</script>

Of cause in this case you cannot use controllers and angular way of getting data. I think you would have to load your data by jQuery, bootstrap your angular in jquery callback and then init your scope variable with data you got from jquery.

Method 3

I guess that the only solution is manually bootstrap your application. Maybe you can find some help in this question Delay Angular App Initialization and in this small article Manually bootstrapping AngularJS for asynchronous loading in Internet Explorer.

As stated in the previous article, to do a manual bootstrap:

angular.element(document).ready(function() {
  angular.bootstrap(document, ["myApp"]);
});

Be sure to remove all the refences of ng-app in your HTML to stop the auto bootstrapping.

Method 4

an other solution since I would not ommit parts of my application but I still have to wait for things to be loaded.

the bootstrap directive (not affiliated to twitter bootstrap) :

myApp.directive('myBootstrap', function() {
  return {
    scope: {
      promise: '=myBootstrap'
    },
    template: '<div ng-if="ctrl.isReady" ng-transclude></div>',
    controllerAs: "ctrl",
    transclude: true,
    controller: function($scope) {
      var ctrl = this;
      ctrl.isReady = false;

      //else an array of promises can be filled by a service
      $scope.promise.then(function() {
          ctrl.isReady = true;
      });
    }
  };
});

and the related plnkr : http://plnkr.co/edit/vx4aWS?p=preview

Note: Use and implement method 1 because this method fully tested our system.
Thank you 🙂

All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply