2

A little more elaboration:

Say I have a service:

app.service('MyService', function(SomeWebSocketService) {
  function MyService() {
    this.object = {};
  }
  MyService.prototype.subscribe = function() {
    var self = this;
    SomeWebSocketService.subscribe('someTopic', function(data) {
      angular.extend(self.object, data);
    }
  }
  return MyService;
}

// usage
app.controller('MyController', function($scope, MyService) {
  var model = new MyService();
  $scope.object = model.object;
});

When I get messages from the WebSocket service, I'd like the $digest loop to trigger. My first inclination was to do something like this:

app.service('MyService', function(SomeWebSocketService) {
  function MyService(scope) {
    // scope from wherever this service was called
    this.scope = scope;
    this.object = {};
  }
  MyService.prototype.subscribe = function() {
    var self = this;
    SomeWebSocketService.subscribe('someTopic', function(data) {
      angular.extend(self.object, data);
      self.scope.$apply();
    }
  }
  return MyService;
}

// usage
app.controller('MyController', function($scope, MyService) {
  var model = new MyService($scope);
  $scope.object = model.object;
});

But I don't like having to pass in some arbitrary scope. So I thought of doing this:

app.service('MyService', function($rootScope, SomeWebSocketService) {
  function MyService() {
    this.object = {};
  }
  MyService.prototype.subscribe = function() {
    var self = this;
    SomeWebSocketService.subscribe('someTopic', function(data) {
      angular.extend(self.object, data);
      $rootScope.$apply();
    }
  }
  return MyService;
}

// usage
app.controller('MyController', function($scope, MyService) {
  var model = new MyService();
  $scope.object = model.object;
});

Will I take a performance hit for doing this? Or is calling $apply on one $scope the same as calling $apply on any?

scniro
  • 16,844
  • 8
  • 62
  • 106
AndyPerlitch
  • 4,539
  • 5
  • 28
  • 43
  • 4
    put it this way...would you want to paint the whole house when you get a chip in the front door, or just paint the door? Run a perf test in jsPerf.com and can find out which works better – charlietfl Jul 08 '14 at 01:07
  • Have you considered using promises rather than calling $apply() directly? If you look at your console.log, you may have many exceptions due to calling apply directly. – Brian Webb Jul 08 '14 at 01:18
  • hmm I get the sense that $http requests automatically trigger digest loops. If that's the case, what's the magic there? – AndyPerlitch Jul 08 '14 at 01:22
  • 1
    @Brian promises won't work in my actual use-case, which involves websockets. So the update function would actually be more like a subscribe function, and the object gets updated periodically after subscribe is called. – AndyPerlitch Jul 08 '14 at 01:35
  • IMHO, the service is the wrong place to use $scope.$apply(). It should be used at the point where the service's update() called... in this case, probably in the handler for whatever web sockets event you're listening for. – Anthony Chu Jul 08 '14 at 04:33
  • @AnthonyChu the problem is that the service itself (which in this case is more like a class that gets instantiated) has the actual handler. I have updated the code to better show my use-case. – AndyPerlitch Jul 08 '14 at 15:14
  • 3
    http://stackoverflow.com/questions/17868889/running-apply-on-rootscope-vs-any-other-scope – user1234 Jul 08 '14 at 15:41
  • 1
    Thanks @Tim. I also found this question that shed some light: http://stackoverflow.com/questions/21658490/angular-websocket-and-rootscope-apply. I think i'll vote to close this as a duplicate. – AndyPerlitch Jul 08 '14 at 15:47
  • Just wanted to mention that there are other approaches that don't need to explicitly call `$apply()`. I tried out [angular-socket-io](https://github.com/btford/angular-socket-io) and noticed it uses the `$timeout` [service instead](https://github.com/btford/angular-socket-io/blob/master/socket.js#L20). In the end this will trigger a digest too, but it might offer a slight benefit over triggering a digest manually. Pure speculation, but it feels cleaner to me. – Sunil D. May 11 '15 at 16:56

0 Answers0