2015-11-03 73 views
1

我有一个服务为我的websocket连接和此服务返回一个函数的实际状态,无论客户端是否实际连接。 我已经简化我的代码,而这些片段是我的问题的一个小例子:

myApp.factory('Websocket', function() { 
    //the status boolean whether connected or not 
    var bool = true; 

    //small mock for the status change 
    setInterval(function() { 
     bool = !bool; 
    }, 1000); 

    //i've made the value of the status variable accessable in a function or the variable itself 
    return { 
     status: function() { 
      return bool; 
     }, 
     var: bool 
    } 
}); 

现在我试图状态值适用于我的范围,控制器:

myApp.controller('Ctrl', function(Websocket, $scope) { 
    //method 1 
    $scope.status = Websocket.status(); 

    //method 2 
    $scope.$watch(function() { 
    return Websocket.status(); 
    }, function(newVal) { 
    $scope.status = newVal; 
    }); 
}); 

...但是这两种方法不工作,没有为这个网站更新$范围变量:

<div ng-app="myApp"> 
    <div ng-controller="Ctrl"> 
     method1: {{status}} 
    </div> 
</div> 

这是一个codepen:http://codepen.io/anon/pen/bVjaBa?editors=101

感谢您的帮助!

回答

1

问题是,由Angular观看的数据的任何“外部”更改都需要呼叫scope.$apply()以供观察者更新(这里的观察者是来自{{status}}表达式的UI)。在codepen解决方法很简单:让服务依赖于$rootScope和间隔功能调用$rootScope.$apply()

myApp.factory('Websocket', function($rootScope) { 
    ... 
    setInterval(function() { 
     bool = !bool; 
     $rootScope.$apply(); 
    }, 1000); 
    ... 
}); 

类似的东西,必须与真正的服务完成的,关键的概念是:(1)你有拨打$apply()和(2)无法访问特定范围,只需使用$rootScope即可。

+0

感谢您的帮助! – Sim

+0

我会使用$ rootScope。$ digest而不是$ apply - 因为您所做的只是跳过try/catch语句以达到相同的结果。 [源(https://github.com/angular/angular.js/blob/v1.2.16/src/ng/rootScope.js#L886)。不是很昂贵,但是,没有真正的理由这样做。 –

2

问题在于Nikos提到:您正在更改摘要循环外的变量值,因此角度不会跟随更改。

使用$scope.$apply是一种选择,但在这种情况下,我宁愿使用$interval而不是setInterval

myApp.factory('Websocket', function($interval) { 
    var bool = true; 
    $interval(function() { 
    bool = !bool; 
    }, 1000); 

    return { 
    status: function() { 
     return bool; 
    }, 
    var: bool 
    } 
}); 

看到它工作here

+0

感谢您的帮助! – Sim