mar*_*k12 24 javascript websocket angularjs
我正在玩一个角度应用程序,它使用websocket与后端进行通信.我在使角度的数据绑定正常工作时遇到了一些麻烦.
在下面的示例中,我创建了一个创建websocket连接的服务.如果websocket收到消息,我只需将该消息推送到包含所有收到的消息的数组中.
在我的控制器中,我将该消息数组绑定到作用域,然后用于ng-repeat在部分视图中列出它们.
服务:
factory('MyService', [function() {
var wsUrl = angular.element(document.querySelector('#ws-url')).val();
var ws = new WebSocket(wsUrl);
ws.onopen = function() {
console.log("connection established ...");
}
ws.onmessage = function(event) {
Service.messages.push(event.data);
}
var Service = {};
Service.messages = [];
return Service;
}]);
Run Code Online (Sandbox Code Playgroud)
控制器:
controller('MyCtrl1', ['$scope', 'MyService', function($scope, MyService) {
$scope.messages = MyService.messages;
}])
Run Code Online (Sandbox Code Playgroud)
部分:
<ul>
<li ng-repeat="msg in messages">
{{msg}}
</li>
</ul>
Run Code Online (Sandbox Code Playgroud)
但是这不能正常工作.当收到新消息并将其推送到阵列中时,应显示所有消息的列表不会更新.我预计它会因为角度双向数据绑定而更新.
我找到了一个解决方案,它通过将消息的推送包装到服务中的调用中来$rootScope.apply()实现:
ws.onmessage = function(event) {
$rootScope.$apply(function() {
Service.messages.push(event.data);
});
}
Run Code Online (Sandbox Code Playgroud)
我的问题是:
这是角度的预期行为,如果我不使用,我的列表不会自动更新$rootScope.apply()吗?
为什么我甚至需要把它包起来$rootScope.apply()?
是用$rootScope.apply()正确的方法来解决这个问题?
$rootScope.apply()这个问题有更好的替代方案吗?
Jul*_*ano 34
是的,AngularJS的绑定是"基于回合的",它们只触发某些DOM事件和对$apply/的调用$digest.有一些有用的服务,比如$http和$timeout为你做包装,但除此之外的任何东西都需要调用$apply或者$digest.
您需要让AngularJS知道您已经更改了绑定到范围的变量,以便它可以更新视图.还有其他方法可以做到这一点.
这取决于你需要什么.在包装代码时$apply(),AngularJS将代码包装在内部angularjs日志记录和异常处理中,当它结束时,它会传播$digest到所有控制器的作用域.在大多数情况下,包装$apply()是最好的方式,它会留下更多的门,以便将来最终使用的角度特征.这是正确的方法吗?参见下文.
如果您不使用Angular的错误处理,并且您知道您的更改不应传播到任何其他范围(根,控制器或指令),并且您需要优化性能,则可以$digest专门调用控制器$scope.这样脏检查就不会传播.否则,如果您不希望Angular捕获错误,但需要将脏检查传播到其他控制器/指令/ rootScope,您可以使用$包装,而不是在进行更改后apply调用$rootScope.$apply().
进一步参考:
$applyvs$digest
| 归档时间: |
|
| 查看次数: |
25427 次 |
| 最近记录: |