$ watch不起作用,让我发疯

时间:2016-02-15 11:36:20

标签: angularjs sockets events

所以,我基本上想要的是用户的套接字连接的可视化。表示客户端是否通过socket.io连接到服务器的指示。

因此我有跟踪套接字状态的服务:

[...]
.factory('DataConnection', function(CONN_EVENTS, socket, $rootScope) {
    var dataConnection = {};

    dataConnection.states={
        // indicates if the user can interact with the ui
        uiEnabled: false,
        [...]
    };
    // socket IO connection states
    $rootScope.$on(CONN_EVENTS.socketAuth, function() {
        dataConnection.states.uiEnabled = true;
    });
    $rootScope.$on(CONN_EVENTS.socketUnAuth, function() {
        dataConnection.states.uiEnabled = false;
    });
    $rootScope.$on(CONN_EVENTS.socketConnLost, function() {
        dataConnection.states.uiEnabled = false;
    });
}

根据事件设置状态。此事件在处理套接字事件的其他服务/工厂中发出。

我尝试了很多方法来将这些值与我的控制器同步。它有点使用手册$scope.$apply(),但有时它给了我apply already in progress错误,因为它非常糟糕的做法,我决定不使用它。

我最终在我的控制器中找到了这个解决方案:

.controller("MainCtrl", function($scope, DataConnection) {
    $scope.$watch(function() {
        return DataConnection.states.uiEnabled
    }, function(uiEnabled) {
        $scope.uiEnabled = uiEnabled;
    }, true);

哪个不想以某种方式工作。当套接字断开连接(服务器关闭)时,ui将不会更新。在交互之后(例如触发弹出窗口),ui将按预期更新。 有什么我想念的吗?或者别的什么我可以尝试?

4 个答案:

答案 0 :(得分:1)

好的,这不是让$ watch工作的解决方案,而只是一种解决方法,“可能”让你的第一种方法使用事件工作而不会丢弃已经在进行中的摘要错误。所以不要使用$ scope。$ apply()包含你在$ timeout(function())内所做的更改,而不是像这样

getpass

注意以上实际上没有添加超时。为什么我认为这可能有效是因为$ timeout会自动应用脚本内部完成执行后所做的任何更改(即,它类似于$ scope。$ spply(),它不会抛出正在进行的摘要周期错误)。我不确定这个,但试试看。

答案 1 :(得分:1)

我只是建议您使用$ scope。$ applyAsync(),这意味着如果正在申请,它将仅在下一个$ digest上执行。

答案 2 :(得分:1)

对我来说,你的方法是好的,看一个返回要观察的对象的函数,我不知道会出现什么问题,但我会使用回调:

.factory('DataConnection', function(CONN_EVENTS, socket, $rootScope) {
    var dataConnection = {};

    dataConnection.states={
        _uiEnabledBackingField: false,
        // indicates if the user can interact with the ui
        uiEnabled: function(val) {
            if (typeof val !== 'undefined') {
                 this._uiEnabledBackingField = val;
                 this.callback(val);
                 return;
            }
            return this._uiEnabledBackingField;
        },
        onUiEnabled: function(cb){ 
           if (cb) {
              this.callback = cb;
           }
        }
    };
});

然后在我的控制器中:

.controller("MainCtrl", function($scope, DataConnection) {
    dataConnection.states.onUiEnabled(function(uiEnabled){
        $scope.uiEnabled = uiEnabled;
    });
});

答案 3 :(得分:0)

我做了一些研究,这是我的结论: $ apply将在三种不同的情况下触发(Exploring Angular 1.3: Go fast with $applyAsync)在我的情况下(我必须在套接字事件后更新DOM),$ apply必须手动触发。

此示例也可在Angular Wiki

中找到
  

如果您正在创建AngularJS服务(例如套接字),它应该有一个$ scope。$ apply()它会触发回调。

我试图在套接字服务中触发$ apply(而不是控制器),这样做效果更好,并没有给我&#34; $ apply已经在进行中的错误&#34;。< / p>