Search code examples
google-app-engineangularjschannel-apiangularjs-service

How can I use Channel API in service without setting $rootScope variable


My issue is that I can't figure out how to receive a message from the channel api without referencing the message in $rootScope. Here's a snippet of the service:

myapp.factory('myService', function($http, $rootScope){
var that = this;
var result;
var onOpened = function(){
    console.log("It opened");
}
onMessage = function(message){
    $rootScope.myMessage = JSON.parse(message.data); // this works
    $rootScope.$apply();                             // but I don't wanna use it
}

var channel = new goog.appengine.Channel('{{ token }}'); // yes, I'm mixing frameworks, relax...
var socket = channel.open();
socket.onopen = onOpened;
socket.onmessage = onMessage;


// I should be returning the onMessage result here, and somehow watching it
})

I can't figure out how to return the results of the onMessage function to the controller without rootscope being invoked.

The controller is straightforward:

myapp.controller('cntrl1', function($scope, $rootScope, myService){
  // It seems that a watch would work but I can't figure out how to 
    // get the 'return' of the service wired to allow this method to be successful.
    // Remember, the onMessage is a json message sent from another client through the 
    // server.  

    $scope.message = $rootScope.myMessage // not necessary

$scope.$watch('myService.parsed', function(newVal, oldVal, scope){      
    if(newVal){
        console.log("changed");
        scope.message = newVal.data;
    } else {
        console.log(oldVal);
        scope.message = oldVal;
    }
})
})

I know that every time the global namespace is polluted a puppy dies, but in this case, I may have to sacrifice a puppy. I'm stuck.


Solution

  • So after some more reading, I found $broadcast and $on to be the solution. (I was too busy looking up examples of $watch to realize the easiest answer was here all along.)

    In the service/factory:

    myapp.factory('myService', function($http, $rootScope){
    var cleanMessage;
    var onOpened = function(){
        console.log("BOO");
    }
    onMessage = function(message){      
        cleanMessage = JSON.parse(message.data);
        $rootScope.$broadcast('newMessage', cleanMessage);
        $rootScope.$apply();        
    }
    
    var channel = new goog.appengine.Channel('{{ token }}');
    var socket = channel.open();
    socket.onopen = onOpened;
    socket.onmessage = onMessage;   
    })  
    

    The $broadcast is saying to all child scopes that in the case of 'newMessage', the model has changed, so get ready to update...

    In the controller is the $on method:

    myapp.controller('cntrl1', function($scope, $rootScope, myService){
    $scope.$on('newMessage', function(evt, message){
    
        $scope.message = message.data;
    })  
    })