Angular.controller()在.run()AngularJS之前运行

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

我在.run()中有一个ajax调用,它将变量加载到$rootScope中,该变量是与视图关联的控制器中所需的变量。 有时在.controller加载时刷新(F5)时,$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();


});

如何修复此错误。

注意:这并不是对您问题的直接回答。 我刚刚尝试过用一种更常见的方式重写您的代码,以利用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的文档中没有看到这一点