Angular.controller()在.run()AngularJS之前运行
我在.run()中有一个ajax调用,它将变量加载到$rootScope中,该变量是与视图关联的控制器中所需的变量。 有时在.controller加载时刷新(F5)时,$rootScope.SuperCategories中没有任何内容Angular.controller()在.run()AngularJS之前运行,angularjs,Angularjs,我在.run()中有一个ajax调用,它将变量加载到$rootScope中,该变量是与视图关联的控制器中所需的变量。 有时在.controller加载时刷新(F5)时,$rootScope.SuperCategories中没有任何内容 sampleApp.factory('SuperCategoryService', ['$http', '$q', '$rootScope', function ($http, $q, $rootScope){ var SuperCategoryServ
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();
});
如何修复此错误。注意:这并不是对您问题的直接回答。 我刚刚尝试过用一种更常见的方式重写您的代码,以利用Promissions和factory,也许它会给您一些可以改进的想法,从而使异步代码更可预测地工作 控制器调用工厂以获取数据,当承诺得到解决时,您的数据位于
$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;
});
});
在这种情况下,你可以这样做
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();
});
});
您可以使用$rootScope.$watch
执行类似的操作,但是由于watcher已经启动,因此它不适合一次性侦听器
无论如何,顶级控制器对于作用域上的所有初始工作来说都是一个更好的地方,不需要在run()
中执行类似的操作
如何修复此错误
这不是一个bug,而是异步工作流的预期行为。在解决承诺时,你们永远不应该依赖延迟,除非应用程序给你们一个控制其相位的机会(Angular并没有给你们机会)
Angular应用程序按以下顺序运行:
- 模块配置
- 模块运行
- 指令工厂功能
- 指令编译
- 指令控制器(ng控制器也是一个指令,对吗?)
- 指令预链接
- 指令(post)链接
- 路由解析
- 路线控制员
$controllerProvider
进行了修补,那么控制器将谦恭地等待run()
中的“controllerreadysetgo”事件,这可能有一天会发生。现在猜猜,如果指令pre/postlinks严重依赖于拥有控制器实例,将会发生什么情况。2年后:-D
您还可以将控制器逻辑包装为$timeout 0。这将在运行块之后执行控制器逻辑。当您说服务中没有任何内容时,您的意思是
未定义的或[]
?如果是后者,那是因为你的承诺还没有解决。它是空白的。。你能帮我解决这个问题吗?这是正确的方法。您正在尝试对数据加载事件计时。有两种方法可以做到这一点,但在这两种情况下,答案都是一个承诺(就像shershen上面所说的)。否则,您只是在抢占应用程序引导发生的顺序(即使这样,您也不能保证数据在那里)。我建议服务保存这些数据。在这种情况下,每当控制器被点击时,它都会调用SuperCategoryService.SuperCategories()函数,该函数在内部发出ajax请求。我想避免ajax请求。所以在app.run()中,我发出了ajax请求,并试图将数据保存在$rootScope变量中。为什么控制器会多次命中?当然,除非是路由器的控制器。你确定吗?我在angular JS的文档中没有看到这一点