我有一个应用程序,它有一些特定的(非平凡的)初始化要求,目前还不清楚最佳实践解决方案是什么。对不起,文字墙。这个问题本身并不复杂,但我需要确保我的推理清楚。
首先,应用程序本身:
- 它具有用户身份验证,但仅在两个时间点强制执行:
- 第一次加载应用程序(第一次)。我将在剩下的问题中将此要求称为 (1)。
- 在与服务器端交互时根据需要。这部分我已经用类似于http://ngmodules.org/modules/http-auth-interceptor的东西解决了,虽然是一个自定义解决方案(这是必需的,因为应用程序需要使用一些我不想成为的服务角度依赖)。我将在剩下的问题中将此要求称为 (2)。
- 有两个与此问题相关的控制器:
- 导航栏控制器(固定,未绑定到视图)。
- 应用于所用视图的控制器(ng-view)。
- 它是使用 angular.bootstrap 手动启动的。
这个问题是关于用户身份验证处理的。要求 (2) 已经解决了用户必须根据需要进行身份验证的情况。目前处理如下:
- 一些服务器端请求由我的 Angular 服务模块之一执行。如果应用的身份验证令牌已过期(或根本不存在),则该请求可能会导致 401 响应。
- 发出请求的应用程序服务模块发现 401 响应并应用 $rootScope.$broadcast('app:auth')。
- 身份验证广播由使用 $scope.$on('app:auth') 的某些代码获取,显示模式身份验证对话框,然后确保原始服务请求承诺已解决/拒绝(如果用户按下取消则拒绝对话)。
要求 (1) 和 (2) 之间的唯一区别是 (1) 应该是强制身份验证对话框(用户不能简单地使用“取消”或“esc”按钮拒绝它)并且 (1) 应该尽早发生尽可能在应用程序初始化中。
现在,我的问题实际上是要求 (1) 和 Angular 最佳实践。我可以看到有几种方法可以做到这一点:
完全在 Angular 之外执行这一一次性身份验证。这里的缺点显然是我必须为模式对话框和初始化编写基本上重复的逻辑。其中一些可以共享,但不是全部。
在应用程序的某些特殊(固定)控制器(如导航栏控制器)中执行此一次性身份验证。
在 angular.module.run 中执行此一次性身份验证。
这里的目的显然是在用户(或应用程序)可以触发应用程序中的其他内容之前“强制”对用户进行身份验证。
我很想使用数字 (3),因为这样我就可以重用所有已按要求 (1) 使用的代码。但是,您随后会遇到将事件侦听代码放置在何处的问题。此时尚未启动应用程序的任何控制器/部分(只有注入完成)。
如果我将身份验证事件的逻辑放在应用程序控制器中,则该控制器甚至不会在那时启动,因此将无法注册该事件。如果我将 $rootScope.$broadcast 放置在延迟为 0 的 $timeout 中,我的导航栏控制器已经启动,但不是我的视图绑定控制器。如果我将 $rootScope.$broadcast 放置在延迟为 100 毫秒的 $timeout 中,则我的两个控制器都已启动(在我的计算机上)。
问题显然是我需要使用的延迟量取决于计算机以及事件处理程序代码的确切范围。它也可能取决于Angular初始化在整个DOM中找到的控制器的确切顺序。
(3) 的替代版本也可能是在 angular.module.run 中执行 $rootScope.$broadcast,并将事件侦听器附加到 $rootScope 本身。我倾向于这是最直接的方式来做到这一点。
请参阅以下 plunker(仅试图突出显示时间问题):http ://plnkr.co/edit/S9q6IwnT4AhwTG7UauZk
所有这些都归结为以下最佳实践问题,真的:
应用程序范围的代码和重要的应用程序初始化代码应该真正放在哪里?我应该将 $rootScope 视为实际的“应用程序”吗?
谢谢!