将会话数据与其他角度指令和控制器同步

时间:2014-02-27 04:34:47

标签: javascript angularjs session angularjs-directive angular-services

在我的AngularJS应用程序中,我有一个Session服务对象,其中包含当前用户,他们的首选项,他们所属的当前公司以及他们正在使用的当前主题等内容。我的应用程序中的许多地方在需要获取此数据时都会引用会话服务。

因为这些变量在服务中,所以我无法使用范围监视来检测更改。所以相反,我决定使用观察者模式。应用程序中的各个位置(例如其他服务,指令,控制器等)将使用会话服务进行注册,并提供在会话更改时执行的回调。

例如,如果用户更改其主题,则会通知使用自定义指令的<style>中的index.html元素,并且它将重新创建新颜色的所有重写css规则。

再例如,每当更新用户的化身时,将通知主菜单栏控制器刷新并重绘头像。像这样的东西。

显然,在各种控制器,指令等使用Session之前,Session中的数据必须至少刷新一次。要求Session服务获取其会话数据的自然位置是应用程序级模块的run块。这很好用,但我认为这也不是最好的地方。

我注意到的一个问题是,当Firebug打开时,加载事物的异步性质会导致排序问题。例如,在<style>元素上运行的指令将在会话服务在应用程序的运行块中刷新后运行...这意味着在按F5后主题将不会更新,因为回调是在初始化后注册的发生的数据。我必须在这里调用手动刷新以保持同步,但如果我这样做,它可能会在订单不同的时间执行两次!这是个大问题。我不认为这个问题只与Firebug有关......它可能在任何情况下都会发生,但Firebug似乎会导致它一致,这很糟糕。

回顾一下......这种异步排序很好:

  1. 主题指令注册回调到会话
  2. 菜单栏应用程序控制器注册回调到会话
  3. .run块中调用Session.refresh()。
  4. 这种异步排序很糟糕:

    1. 菜单栏应用程序控制器注册回调到会话
    2. .run块中调用Session.refresh()。
    3. 主题指令注册回调会话,但由于Session.refresh()已经执行,因此回调不会被执行。
    4. 因此,不是使用观察者模式,或通过run块刷新会话状态,设计服务的最佳方式等等,以便会话数据总是在之后(或者之前)刷新)应用程序的其他各个部分需要它吗?在执行指令和控制器而不是运行块之前,是否存在某种可以挂钩的事件?

      如果我的方法通常是合理的,我可以添加什么来真正使它按照应有的方式工作?

      谢谢!

2 个答案:

答案 0 :(得分:1)

在angular.js中,您有两种使用全局变量的方法:

  1. 使用$ rootScope
  2. 使用服务
  3. 使用$ rootScope非常简单,因为您只需将其注入任何控制器并更改此范围内的值即可。所有全局变量都有问题! 服务是单身人士(你需要什么)!

    我认为在你的情况下你可以使用

      

    $ rootScope

      

    $范围。$观看

    很棒answer

答案 1 :(得分:0)

有没有理由不能像这样直接访问变量:

app.factory('SessionService', function() {
    var items = {
        "avatar": "some url"
    };
    return items;
});

var MainController = [$scope, 'SessionService', function($scope, SessionService){
    $scope.session = SessionService;

    $scope.modifyAvatar = function(url){
        $scope.session.avatar = "some new url";
    };
}];

var HeaderController = [$scope, 'SessionService', function($scope, SessionService){
    $scope.session = SessionService;

    // You probably wouldn't do this, you would just bind
    // to {{session.avatar}} in your template
    $scope.getAvatar = function(){
        return $scope.session.avatar;
    };
}];