Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angularjs/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
处理非平凡AngularJS应用程序初始化需求的最佳实践?_Angularjs_Angularjs Scope - Fatal编程技术网

处理非平凡AngularJS应用程序初始化需求的最佳实践?

处理非平凡AngularJS应用程序初始化需求的最佳实践?,angularjs,angularjs-scope,Angularjs,Angularjs Scope,我有一个应用程序,它有一些特定的(非琐碎的)初始化需求,但目前还不清楚这方面的最佳实践解决方案是什么。对不起,这是文字墙。问题本身并没有那么复杂,但我需要确保我的推理是清楚的 首先,应用程序本身: 它具有用户身份验证,但仅在两个时间点强制执行: 第一次加载应用程序时(第一次)。我将把这个要求称为(1)通过问题的其余部分 在与服务器端交互时,基于需要。我已经用类似的方法解决了这一部分,不过是一个自定义解决方案(这是必需的,因为应用程序需要使用一些我不想依赖的服务)。我将把这个要求称为(2)通过问

我有一个应用程序,它有一些特定的(非琐碎的)初始化需求,但目前还不清楚这方面的最佳实践解决方案是什么。对不起,这是文字墙。问题本身并没有那么复杂,但我需要确保我的推理是清楚的

首先,应用程序本身:

  • 它具有用户身份验证,但仅在两个时间点强制执行:
  • 第一次加载应用程序时(第一次)。我将把这个要求称为(1)通过问题的其余部分
  • 在与服务器端交互时,基于需要。我已经用类似的方法解决了这一部分,不过是一个自定义解决方案(这是必需的,因为应用程序需要使用一些我不想依赖的服务)。我将把这个要求称为(2)通过问题的其余部分
  • 有两个控制器与此问题相关:
    • 导航栏控制器(固定,未绑定到视图)
    • 应用于所用视图的控制器(ng视图)
  • 它是使用angular.bootstrap手动启动的
这个问题是关于用户身份验证处理的。用户必须根据需要进行身份验证的要求(2)已经解决。它当前的处理方式如下所示:

  • 一些服务器端请求由我的一个角服务模块执行。如果应用的身份验证令牌已过期(或不同时存在),则请求可能导致401响应
  • 发出请求的应用程序服务模块发现401响应并应用$rootScope.$broadcast('app:auth')
  • 一些代码使用$scope.$on('app:auth')拾取身份验证广播,显示模式身份验证对话框,然后确保原始服务请求承诺已解决/拒绝(如果用户在对话框中按取消,则拒绝)
  • 需求(1)和(2)之间的唯一区别在于(1)应该是一个强制身份验证对话框(用户不能简单地用“取消”或“esc”按钮拒绝它),并且(1)应该尽可能早地在应用程序初始化时发生

    现在,我的问题是需求(1),实际上,是角度最佳实践。有几种方法可以做到这一点,我可以看到:

  • 在外部执行此一次性身份验证。这里的缺点显然是,我必须为模式对话框和初始化编写本质上重复的逻辑。其中一些可以共享,但不是全部

  • 在应用程序的某些特殊(固定)控制器(如导航栏控制器)中执行此一次性身份验证

  • 在angular.module.run中执行此一次性身份验证

  • 这里的目的显然是在用户(或应用程序)触发应用程序中的其他内容之前“强制”用户进行身份验证

    我希望使用数字(3),因为这样我就能够重用需求(1)中已经使用的所有代码。但是,您随后会遇到将事件侦听代码放置在何处的问题。此时尚未启动应用程序的任何控制器/部分(只有注入完成)

    如果我将身份验证事件的逻辑放在应用程序控制器中,则该控制器甚至不会在该点启动,因此无法向事件注册。如果将$rootScope.$broadcast放置在延迟为0的$timeout内,则导航栏控制器已启动,但视图绑定控制器未启动。如果我将$rootScope.$广播置于延迟100毫秒的$timeout内,则我的两个控制器都已启动(在我的计算机上)

    问题显然是,我需要使用的延迟量取决于计算机以及事件处理程序代码的确切作用域。这也可能取决于通过DOM找到的控制器的初始化顺序

    (3)的另一个版本可能是在angular.module.run中执行$rootScope.$broadcast,并将事件侦听器连接到$rootScope本身。我倾向于这样做,因为这是最直接的方式

    请参阅以下plunker(仅尝试解决计时问题):

    所有这些都归结为以下最佳实践问题:

    应用程序范围的代码和非平凡的应用程序初始化代码应该放在哪里?我是否应该把$ROOTSCOPE视为实际的“应用程序”?< /强>

    谢谢

    简短的回答是:

    应用程序范围的代码应该在服务中

    应用程序初始化代码应位于
    运行
    块中

    详细回答:

    应用程序范围的代码(如身份验证)应该在服务中定义。该服务应该公开应用程序的其余部分可以与之交互的API,以便完成该任务。当然,服务的工作是隐藏实现细节。服务本身应该注意从何处获取身份验证信息(最初)-可能从cookie,可能从本地存储或会话存储。。或者它甚至可以进行http调用。但所有这些都被封装到了认证服务中

    因为现在您已经编写了一个单独的服务,并且可以
    东西注入到您的run块中,所以您可以继续了。您实际上并不需要
    $rootScope
    $rootScope
    是另一个注入式服务。但是因为它参与了脏检查机制,而且似乎这个服务不需要。。您不需要为$rootScope增加额外任务的负担。这不是它的工作,也许它可以委托给其他一些服务,这些服务的唯一任务是身份验证。因为
    app.provider('service', function() {
    
        // add method to configure your service
       this.configureService = function() { ... };
    
       this.$get = function (/*injectibles*/) {
            // return the service instance
            return {...}; 
       };
    
    });
    
    app.config(function(serviceProvider) { 
    
        serviceProvider.configureService();
        serviceProvider.setTimeout(1000);
        serviceProvider.setVersion('1.0);
        serviceProvider.setExternalWebService('api/test');
    
        ... more configuration ...
    };