title: Angular - Websocket and $rootScope.apply()
body: <p>I'm currently playing around with an angular app that uses a websocket to communicate with the backend. I've had some trouble getting angular's data binding working correctly.</p>
  
  <p>In the example below I've created a service which creates the websocket connection. If the websocket receives a message I just push that message into an array which contains all of the received messages.</p>
  
  <p>In my controller I bind that array of messages to the scope and then use <code>ng-repeat</code> to list them all in my partial view. </p>
  
  <p><strong>Service:</strong></p>
  
  <pre><code>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;
  }]);
  </code></pre>
  
  <p><strong>Controller:</strong></p>
  
  <pre><code>controller('MyCtrl1', ['$scope', 'MyService', function($scope, MyService) {
    $scope.messages = MyService.messages;
  }])
  </code></pre>
  
  <p><strong>Partial:</strong></p>
  
  <pre><code>&lt;ul&gt;
    &lt;li ng-repeat="msg in messages"&gt;
        {{msg}} 
    &lt;/li&gt;
  &lt;/ul&gt;
  </code></pre>
  
  <p>This however does not work correctly. When a new message is received and pushed into the array, the list that should display all messages does not get updated. I expected it to be updated because of angular two way data binding.</p>
  
  <p>I've found one solution that works by wrapping the pushing of the message into a call to <code>$rootScope.apply()</code> in the service:</p>
  
  <pre><code>ws.onmessage = function(event) {
    $rootScope.$apply(function() {
      Service.messages.push(event.data);
    });
  }  
  </code></pre>
  
  <p>My questions are:</p>
  
  <ol>
  <li><p>Is this the expected behavior of angular that my list does not automatically get updated if I do not use <code>$rootScope.apply()</code> ?</p></li>
  <li><p>Why do I even need to wrap it in <code>$rootScope.apply()</code>?</p></li>
  <li><p>Is using <code>$rootScope.apply()</code> the correct way to solve this?</p></li>
  <li><p>Are there better alternatives to <code>$rootScope.apply()</code> for this problem?</p></li>
  </ol>