3

特定の (自明ではない) 初期化要件を持つアプリケーションがありますが、これに対するベスト プラクティス ソリューションが何であるかが明確ではありません。テキストの壁で申し訳ありません。質問自体はそれほど複雑ではありませんが、私の推論が明確であることを確認する必要があります。

まず、アプリケーション自体:

  • ユーザー認証がありますが、次の 2 つの時点でのみ強制されます。
    1. アプリケーションが初めてロードされたとき (非常に初めて)。残りの質問では、この要件を (1) と呼びます。
    2. サーバー側と対話するときに必要に応じて。この部分は、 http://ngmodules.org/modules/http-auth-interceptorに似たもので既に解決していますが、カスタムソリューション (アプリケーションが私が望まないサービスを使用する必要があるため、これが必要です)角度依存)。残りの質問では、この要件を (2) と呼びます。
  • この質問に関連する 2 つのコントローラーがあります。
    • ナビゲーション バー コントローラー (固定、ビューにバインドされていません)。
    • 使用するビューに適用されるコントローラー (ng-view)。
  • angular.bootstrap を使用して手動で開始します。

この質問は、ユーザー認証の処理に関するものです。ユーザーが必要に応じて認証する必要がある要件 (2) は、既に解決されています。現在、次のように処理されています。

  1. 一部のサーバー側の要求は、Angular サービス モジュールの 1 つによって実行されます。適用された認証トークンの有効期限が切れている (またはまったく存在しない) 場合、要求は 401 応答になる可能性があります。
  2. リクエストを行ったアプリケーション サービス モジュールは 401 レスポンスを検出し、$rootScope.$broadcast('app:auth') を適用します。
  3. 認証ブロードキャストは、$scope.$on('app:auth') を使用するコードによって取得され、モーダル認証ダイアログを表示し、元のサービス リクエストの promise が解決/拒否されていることを確認します (ユーザーがキャンセルを押すと拒否されます)。ダイアログ)。

要件 (1) と (2) の唯一の違いは、(1) は強制認証ダイアログでなければならず (ユーザーは「キャンセル」または「esc」ボタンで単純に拒否することはできません)、(1) はできるだけ早く発生する必要があることです。アプリケーションの初期化で可能な限り。

さて、私の問題は、要件 (1)、実際には、Angular のベスト プラクティスにあります。これを行うにはいくつかの方法があります。

  1. この 1 回限りの認証は、Angular の外部で完全に実行してください。ここでの欠点は、明らかに、モーダル ダイアログ ボックスと初期化の両方に対して本質的に重複したロジックを記述しなければならないことです。一部は共有できますが、すべてではありません。

  2. このワンタイム認証は、アプリケーションの特別な (固定) コントローラー (ナビゲーション バー コントローラーなど) で実行します。

  3. 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 を実際の「アプリケーション」と見なす必要がありますか?

ありがとう!

4

2 に答える 2

0

アプリケーション全体の重要な初期化コードをプロバイダーに配置する必要があります。プロバイダーは、$injector によってサービスのインスタンスが実際に作成される前にサービスを構成するために使用できるため、初期化に関して最も柔軟性があります。

app.provider('service', function() {

    // add method to configure your service
   this.configureService = function() { ... };

   this.$get = function (/*injectibles*/) {
        // return the service instance
        return {...}; 
   };

});

config ブロックは、プロバイダーを初期化する機会です。プロバイダーを構成関数に挿入し (必要な「プロバイダー」サフィックスに注意してください)、プロバイダーのセットアップに必要な初期化コードを実行します。プロバイダーはサービスではないことに注意してください。これは、$injector がサービスを作成するために使用するものです。

app.config(function(serviceProvider) { 

    serviceProvider.configureService();
    serviceProvider.setTimeout(1000);
    serviceProvider.setVersion('1.0);
    serviceProvider.setExternalWebService('api/test');

    ... more configuration ...
};

プロバイダーと構成ブロックが初期化に適している理由はいくつかあります。

  1. config ブロックは、アプリケーション ライフ サイクルの非常に早い段階で 1 回だけ呼び出されます。
  2. プロバイダーは構成可能です。つまり、実際にサービスを作成する前にプロバイダーを初期化できます。
  3. config ブロックの主な目的初期化です。初期化を実行する機会としてプロバイダーの注入をサポートします。
  4. プロバイダーはシングルトン (ファクトリーやサービスなど) です。つまり、$injector によって 1 つのサービス インスタンスが作成され、すべてのコントローラー、ディレクティブなどの間で共有されます。基本的には、サービスが注入されるすべての場所です。

要件(1)と(2)については、正しい方向に進んでいると思います。スコープで監視されている「IsAuthenticated」プロパティに基づいて、モーダル ログイン ダイアログを表示または非表示にする authLogin ディレクティブを作成することをお勧めします。これにより、アプリケーションの起動時にログイン モーダル ダイアログを表示する必要がなくなります。ユーザーが正常に認証されたら、IsAuthenticated プロパティを true に設定します (これにより、ダイアログが非表示になります)。

2 番目の要件は、HTTP インターセプターによって処理されます。要求が行われ、ユーザーが認証されていない場合、サービスは $rootScope から子スコープに向かってイベントをブロードキャストします。IsAuthenticated プロパティを false に設定することで、同じ authLogin ディレクティブでイベントをリッスンして処理できます。IsAuthenticated は監視対象のプロパティであるため、モーダル ログイン ダイアログがトリガーされ、ユーザーが再度ログインできるようになります。

要件 (1) と (2) を実装する方法はたくさんあります。私はあなたのアプローチにわずかなバリエーションを提供しましたが、一般的には同じアプローチです。

于 2014-06-14T10:11:43.613 に答える