特定の (自明ではない) 初期化要件を持つアプリケーションがありますが、これに対するベスト プラクティス ソリューションが何であるかが明確ではありません。テキストの壁で申し訳ありません。質問自体はそれほど複雑ではありませんが、私の推論が明確であることを確認する必要があります。
まず、アプリケーション自体:
- ユーザー認証がありますが、次の 2 つの時点でのみ強制されます。
- アプリケーションが初めてロードされたとき (非常に初めて)。残りの質問では、この要件を (1) と呼びます。
- サーバー側と対話するときに必要に応じて。この部分は、 http://ngmodules.org/modules/http-auth-interceptorに似たもので既に解決していますが、カスタムソリューション (アプリケーションが私が望まないサービスを使用する必要があるため、これが必要です)角度依存)。残りの質問では、この要件を (2) と呼びます。
- この質問に関連する 2 つのコントローラーがあります。
- ナビゲーション バー コントローラー (固定、ビューにバインドされていません)。
- 使用するビューに適用されるコントローラー (ng-view)。
- angular.bootstrap を使用して手動で開始します。
この質問は、ユーザー認証の処理に関するものです。ユーザーが必要に応じて認証する必要がある要件 (2) は、既に解決されています。現在、次のように処理されています。
- 一部のサーバー側の要求は、Angular サービス モジュールの 1 つによって実行されます。適用された認証トークンの有効期限が切れている (またはまったく存在しない) 場合、要求は 401 応答になる可能性があります。
- リクエストを行ったアプリケーション サービス モジュールは 401 レスポンスを検出し、$rootScope.$broadcast('app:auth') を適用します。
- 認証ブロードキャストは、$scope.$on('app:auth') を使用するコードによって取得され、モーダル認証ダイアログを表示し、元のサービス リクエストの promise が解決/拒否されていることを確認します (ユーザーがキャンセルを押すと拒否されます)。ダイアログ)。
要件 (1) と (2) の唯一の違いは、(1) は強制認証ダイアログでなければならず (ユーザーは「キャンセル」または「esc」ボタンで単純に拒否することはできません)、(1) はできるだけ早く発生する必要があることです。アプリケーションの初期化で可能な限り。
さて、私の問題は、要件 (1)、実際には、Angular のベスト プラクティスにあります。これを行うにはいくつかの方法があります。
この 1 回限りの認証は、Angular の外部で完全に実行してください。ここでの欠点は、明らかに、モーダル ダイアログ ボックスと初期化の両方に対して本質的に重複したロジックを記述しなければならないことです。一部は共有できますが、すべてではありません。
このワンタイム認証は、アプリケーションの特別な (固定) コントローラー (ナビゲーション バー コントローラーなど) で実行します。
angular.module.run でこの 1 回限りの認証を実行します。
ここでの目的は、明らかに、ユーザー (またはアプリケーション) がアプリケーションで何かをトリガーできるようになる前に、ユーザーに認証を「強制」することです。
要件 (1) で既に使用されているすべてのコードを再利用できるため、番号 (3) を使用したいと思います。ただし、代わりに、イベントをリッスンするコードをどこに配置するかという問題に直面します。この時点では、アプリケーションのコントローラーやパーツはまだ開始されていません (インジェクションのみが完了しています)。
認証イベントのロジックをアプリケーション コントローラーに配置すると、そのコントローラーはその時点で開始されていないため、イベントに登録できません。$rootScope.$broadcast を $timeout 内に遅延 0 で配置すると、ナビゲーション バー コントローラーは開始されますが、ビュー バインド コントローラーは開始されません。$rootScope.$broadcast を $timeout 内に 100 ミリ秒の遅延で配置すると、両方のコントローラーが (私のコンピューター上で) 開始されます。
問題は、使用する必要がある遅延の量がコンピューターと、イベントハンドラーコードが配置されている正確なスコープに依存していることです。また、Angular が DOM 全体で見つかったコントローラーを初期化する順序にも依存している可能性があります。
(3) の代替バージョンとして、angular.module.run で $rootScope.$broadcast を実行し、イベント リスナーを $rootScope 自体にアタッチすることもできます。私はこれが最も率直な方法であることに傾いています。
次のプランカーを参照してください (タイミングの問題のみを強調しようとしています): http://plnkr.co/edit/S9q6IwnT4AhwTG7UauZk
これはすべて、次のベストプラクティスの質問に要約されます。
アプリケーション全体のコードと重要なアプリケーション初期化コードは、実際にはどこに配置する必要がありますか? $rootScope を実際の「アプリケーション」と見なす必要がありますか?
ありがとう!