Thanks to @calebboyd who made remind me the existence of the $scope
's destroy
event, I think I have found a good way to achieve my requirement.
A semi-automatic way to let the controller unsubscribe itself would be to add this piece of code:
$scope.$on("$destroy",function() {
WebSocketConnection.unsubscribe($scope.$id);
});
Subscribing mechanism would look like this:
WebSocketConnection.subscribe($scope.$id, function (message) { //note the $scope.$id parameter
$scope.$apply(function () {
var data = angular.fromJson(message.data);
$scope.notifications.push(data);
});
});
Therefore, the full factory code would be:
.factory('WebSocketConnection', function () {
var service = {};
service.callbacks = {}; //note the object declaration, not Array
service.connect = function() {
if(service.ws)
return;
var ws = new WebSocket("ws://localhost:9000/ws");
ws.onmessage = function (message) {
angular.forEach(service.callbacks, function(callback){
callback(message);
});
};
service.ws = ws;
};
service.send = function(message) {
service.ws.send(message);
};
service.subscribe = function(concernedScopeId, callback) {
service.callbacks[concernedScopeId] = callback;
};
service.unsubscribe = function(concernedScopeId) {
delete service.callbacks[concernedScopeId];
};
return service;
});
And that does the trick: each useless callback acting as listener can then be detected and deleted.