0

我正在尝试实现用户身份验证系统。我已阅读有关401http 状态代码和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器,因为我们$emitting来自$rootScope- 事件不会遍历您的 $scope 层次结构并导致性能问题。


另一种方式,这是我从控制器处理 $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 回答