В настоящее время я играю с приложением angular, которое использует websocket для связи с бэкэнд. У меня возникли проблемы с правильной работой привязки данных angular.
В приведенном ниже примере я создал службу, которая создает соединение с 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;
}]);
Контроллер:
controller('MyCtrl1', ['$scope', 'MyService', function($scope, MyService) {
$scope.messages = MyService.messages;
}])
Частичная:
<ul>
<li ng-repeat="msg in messages">
{{msg}}
</li>
</ul>
Это, однако, работает неправильно. Когда новое сообщение принимается и вводится в массив, список, который должен отображать все сообщения, не обновляется. Я ожидал, что он будет обновлен из-за angular двусторонней привязки данных.
Я нашел одно решение, которое работает путем переноса нажатия сообщения в вызов $rootScope.apply()
в службе:
ws.onmessage = function(event) {
$rootScope.$apply(function() {
Service.messages.push(event.data);
});
}
Мои вопросы:
-
Является ли это ожидаемым поведением angular, что мой список не обновляется автоматически, если я не использую
$rootScope.apply()
? -
Почему мне даже нужно обернуть его в
$rootScope.apply()
? -
Использует
$rootScope.apply()
правильный способ решить эту проблему? -
Есть ли лучшие альтернативы
$rootScope.apply()
для этой проблемы?