I have an ajax call inside the .run() that loads a variable into the $rootScope That variable is needed in the controller associated with a view. Sometimes on refresh (F5) by the time the .controller is loading there is nothing inside $rootScope.SuperCategories.
sampleApp.factory('SuperCategoryService', ['$http', '$q', '$rootScope', function ($http, $q, $rootScope){
var SuperCategoryService = {};
SuperCategoryService.SuperCategories = $rootScope.SuperCategories;
alert ($rootScope.SuperCategories);
return SuperCategoryService;
}]);
sampleApp.run(function($rootScope, $q, $http) {
var req = {
method: 'POST',
url: 'SuperCategoryData.txt',
//url: 'http://localhost/cgi-bin/superCategory.pl',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }//,
//data: { action: 'GET' }
};
$rootScope.SuperCategories = [];
$rootScope.GetSuperCategories = function () {
var defer = $q.defer();
$http(screq).then(function(response) {
$rootScope.SuperCategories = response.data;
//alert ($rootScope.SuperCategories);
defer.resolve($rootScope.SuperCategories);
}, function(error) {
defer.reject("Some error");
});
return defer.promise;
}
$rootScope.GetSuperCategories();
});
How to fix this bug.
The application runs inside the <div>. The ng-controller="myCtrl" attribute is an AngularJS directive. It defines a controller. The myCtrl function is a JavaScript function. AngularJS will invoke the controller with a $scope object. In AngularJS, $scope is the application object (the owner of application variables and functions).
AngularJS Controllers AngularJS applications are controlled by controllers. The ng-controller directive defines the application controller. A controller is a JavaScript Object, created by a standard JavaScript object constructor.
The ng-controller directive defines the application controller. A controller is a JavaScript Object, created by a standard JavaScript object constructor. The AngularJS application is defined by ng-app="myApp". The application runs inside the <div>.
Calling a function or initializing a single value on page load in AngularJS is quite easy. AngularJS provides us with a dedicated directive for this specific task. It’s the ng-init directive. Syntax: <element ng-init="function()"> Contents... </element> Example 1: In this example we will call a function to initialize a variable on page load. <
NB: this is not directly answer to you question. I've just tried to rewrite your code a little bit in a way to utilize promises and factory more common way, may be it will give you some ideas what can be improved to make the async code work more predictably.
Controller calls factory to get the data, and when Promise is resolved you have you data in $rootScope.SuperCategories
sampleApp.factory('SuperCategoryService', ['$http', '$q', function ($http, $q){
var req = {
method: 'POST',
url: 'SuperCategoryData.txt',
//url: 'http://localhost/cgi-bin/superCategory.pl',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }//,
//data: { action: 'GET' }
};
var SuperCategoryService = {};
SuperCategoryService.SuperCategories = function () {
var defer = $q.defer();
$http(screq).success(function(response) {
defer.resolve(response);
});
return defer.promise;
}
return SuperCategoryService;
}]);
sampleApp.controller('myController', ['$scope', 'SuperCategoryService', function($scope, SuperCategoryService) {
SuperCategoryService.SuperCategories().then(function(data){
$rootScope.SuperCategories = data;
});
});
In such cases you could something like this.
sampleApp.run(function($rootScope, $q, $http) {
...
// once the promise is resolved and SuperCategories are filled
$rootScope.$emit('init');
});
sampleApp.controller('AppCtrl', function ($rootScope) {
function init() {
...
}
var unbindHandler = $rootScope.$on('init', function () {
init();
unbindHandler();
});
});
You can do similar thing with $rootScope.$watch
, but since the watcher has initial launch, it isn't a good fit for one-time listeners.
Anyway, top-level controller is a better place for all initial work on the scope, there's no need to do something like this in run()
.
How to fix this bug.
It is not a bug but the expected behaviour of asynchronous workflow. You should never rely on delays when resolving promises, unless app gives you an opportunity to control its phases (and Angular doesn't give one).
Angular app runs in such order:
Let's assume we monkey-patched $controllerProvider
, so controllers will humbly wait for 'controllersReadySetGo' event from run()
that may happen someday. Now guess what will happen with e.g. directive pre/postlinks that seriously rely on having a controller instance.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With