0

ユーザー認証システムを実装しようとしています。401http status code とHTTP Auth Interceptor Moduleについて読みました。

モジュールを bower でダウンロードし、アプリ モジュールにロードしました。まだ使用していませんが、このモジュールがトリガーするのと同じイベントを使用して、ユーザーがブラウザーでアプリケーションを開いたときにユーザー ログイン ポップアップを表示したいと考えています。

私のコントローラーはすべての子ですCoreController。現在のCoreControllerユーザーを解決します。アプリケーションのロード時にログインしているユーザーがいないため、イベントを発行するログインフォームを表示したい: event:auth-loginRequired(http-auth-interceptor と同じ)。

これCoreControllerには、この特定のイベント ( ) をリッスンする別のルールがありevent:auth-loginRequiredます。このイベントが検出されると、コントローラーはそのstateID を呼び出すポップアップを表示します。

私が抱えている問題は、イベントを正しく発行したとコンソールが言っているが、リスナーがトリガーされていないため、ログインポップアップが表示されないことです。

これが私のものCoreControllerです:

/**
 * Index controller definition
 *
 * @scope Controllers
 */
define(['./../module', 'moment'], function (controllers, moment) {
    'use strict';

    controllers.controller('CoreController', ['$scope', '$rootScope', '$state', 'user', function ($scope, $rootScope, $state, user)
    {
        console.log('Core Controller Loaded');
        $scope.loader = true;

        $scope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams)
        {
            $scope.loader = true;
        });

        $scope.$on('event:auth-loginRequired', function(event, toState, toParams, fromState, fromParams)
        {
            console.log('catch auth required');
            $state.go("main.login");
        });

        if (user.isLogged == false) {
            console.log('emit auth required');
            $rootScope.$emit('event:auth-loginRequired');
        }
    }]);
});

私は何を間違っていますか?

乾杯、マキシム

4

1 に答える 1

9

問題は、あなたが発していて、そのイベントがローカルリスナー$rootScopeに届かないことです。$scope

簡単な方法(非推奨):

    if (user.isLogged == false) {
        console.log('broadcast auth required');
        $rootScope.$broadcast('event:auth-loginRequired');
    }

この解決策の問題点は、イベントが$rootScopeすべての子スコープにバブリングすることです。これは、パフォーマンスの観点からは好ましくありません。


より良い方法(推奨):

    $rootScope.$on('event:auth-loginRequired', function(event, toState, toParams, fromState, fromParams)
    {
        console.log('catch auth required');
        $state.go("main.login");
    });

    if (user.isLogged == false) {
        console.log('emit auth required');
        $rootScope.$emit('event:auth-loginRequired');
    }

ここでは、イベント リスナーを設定しています。イベント$rootScopeは$scope 階層を通過せず、パフォーマンスの問題が発生しません。$emitting$rootScope


もう 1 つの方法 (コントローラーから $rootScope イベント リスナーを処理する方法として私が好む方法) は、ローカルの $scope が破棄されたときにイベント リスナーからサブスクライブを解除することです。

さらに良い方法(強くお勧めします (私の意見では*)):

var mainModule = angular.module('myModule'); // this would be your core module, tying everything together. 

mainModule.config(function ($provide) {
  // Define an alternative to $rootScope.$on. 
  // $scope.subscribe will emulate the same behaviour, with the difference
  // of removing the event listener when $scope.$destroy is called. 

  $provide.decorator('$rootScope', function ($delegate) {
    Object.defineProperty($delegate.constructor.prototype, 'subscribe', {
      value: function (name, listener) {
        var unsub = $delegate.$on(name, listener);
        this.$on('$destroy', unsub);
      },
      enumerable: false
    });

    return $delegate;
  });
});

// Then in your CoreController

 $scope.subscribe('event:auth-loginRequired', function(event, toState, toParams, fromState, fromParams)
  {
      console.log('catch auth required');
      $state.go("main.login");
  });

  if (user.isLogged == false) {
      console.log('emit auth required');
      $rootScope.$emit('event:auth-loginRequired');
  }

$rootScopeこれにより、リスナーを設定するためにコントローラーに注入する必要がなくなります$rootScope(ただし、これはエミッターの設定には当てはまりません)。

どちらの方法でこれに取り組むにしても、解決策 2 または 3 を検討することを強くお勧めします。#1は絶対にお勧めできません。

幸運を!

于 2014-05-27T11:14:33.017 に答える