Angular SockJS service problem

1,003 views
Skip to first unread message

Paul Liu

unread,
Apr 27, 2013, 1:36:18 PM4/27/13
to ang...@googlegroups.com
I am a noob in Angular and struggling with using SockJS with Angular. I have created a service following the pattern suggested by Brian Ford in his Socket.IO tutorial

I replaced 

app.factory('socket', function ($rootScope) {
  var socket = io.connect();
  return {
    on: function (eventName, callback) {
      socket.on(eventName, function () {  
        var args = arguments;
        $rootScope.$apply(function () {
          callback.apply(socket, args);
        });
      });
    },
    emit: function (eventName, data, callback) {
      socket.emit(eventName, data, function () {
        var args = arguments;
        $rootScope.$apply(function () {
          if (callback) {
            callback.apply(socket, args);
          }
        });
      })
    }
  };
});


with 

 var socket = SockJS('/echo');

  return {
    onmessage: function (eventName, callback) {
      socket.onmessage(eventName, function () {  
        var args = arguments;
        $rootScope.$apply(function () {
          callback.apply(socket, args);
        });
      });
    },
    send: function (eventName, data, callback) {
      socket.send(eventName, data, function () {
        var args = arguments;
        $rootScope.$apply(function () {
          if (callback) {
            callback.apply(socket, args);
          }
        });
      });
    }
  };

With this modification, socket.send is working but socket.onmessage dose not. I wonder if anyone can give me a hint on how to solve this problem

Thanks.

Paul



Paul Liu

unread,
Apr 28, 2013, 4:35:42 AM4/28/13
to ang...@googlegroups.com
After some digging, I located this on github:


If I use  $rootScope.$broadcast() inside of onmessage then it started to work in my program.

Is this a good practice? or is there a better approach?

Paul

Pradyut Pokuri

unread,
Sep 5, 2013, 2:34:43 PM9/5/13
to ang...@googlegroups.com
Hi Paul,

Where you able to figure why $broadcast was necessary? Also did you just replace $apply with $broadcast?

Thanks,
Prad

Paul Liu

unread,
Sep 5, 2013, 8:24:03 PM9/5/13
to ang...@googlegroups.com
Hi Prad,

Similar to what Bretto did in the following code:


I a service that use sock.js to communicate with server and access it from a directive with dependency injection.
In the directive, I use scope.$on to watch the message and process it. I think this require $broadcast to make it work.

Paul

Pradyut Pokuri於 2013年9月6日星期五UTC+8上午2時34分43秒寫道:

Pradyut Pokuri

unread,
Sep 9, 2013, 12:12:48 PM9/9/13
to ang...@googlegroups.com
Thanks! I'll give it a try today.


On Saturday, April 27, 2013 12:36:18 PM UTC-5, Paul Liu wrote:

Pradyut Pokuri

unread,
Sep 19, 2013, 2:58:18 PM9/19/13
to ang...@googlegroups.com
Hi Paul, 

I tried what you recommended. This is what I have

factory('sockjs', function ($rootScope) {
  
    var conn = new SockJS(
      'http://' + window.location.hostname + ':8080/socket', ["websocket", "xhr-streaming", "iframe-eventsource", "iframe-htmlfile", "xhr-polling", "iframe-xhr-polling", "jsonp-polling"]
    );
    return {
      onmessage: function (eventName, callback) {
        $rootScope.$broadcast('sockjsmsg', arguments);
       
        conn.onmessage(eventName, function () {  
          $rootScope.$broadcast('sockjsmsg', arguments);
          var args = arguments;
          $rootScope.$apply(function () {
            callback.apply(conn, args);
          });
        });
    },
      send: function (eventName, data, callback) {
        conn.send(eventName, data, function () {
          var args = arguments;
          $rootScope.$apply(function () {
            if (callback) {
              callback.apply(conn, args);
            }
          });
        });
      }
    };
  });

However I still don't get it to broadcast. Any suggestions?

THanks again,
Prad


On Saturday, April 27, 2013 12:36:18 PM UTC-5, Paul Liu wrote:

Paul Liu

unread,
Sep 19, 2013, 11:21:21 PM9/19/13
to ang...@googlegroups.com
Hi Prad,

I did not write it that way. Here is what I did in the service:

.factory('socket', ['$rootScope', '$location', function($rootScope, $location){

  function init() {
      var scServer = new SockJS("/sockserver1");

        // On successful connection
        scServer.onopen = function (event) {
            //do some stuff
        };

        // On message received
        scServer.onmessage = function (event) {
scServer.payload = event.data;
            $rootScope.$broadcast('incomingData', event);
        };

        // On socket close
        scServer.onclose = function (event) {
            scServer = null;
            //do some stuff
        }
   init();

    console.log('scServer created');
    return scServer;
  
}]);

In the controller or directive where you want to get the data:

//inject the socket
.directive('myDirective',['socket', function(socket){

          scope.$on('incomingData',function (e) {
                var m = JSON.parse(socket.payload);

You will be able to access your data from variable 'm';

I hope this will help you.

Best Regards
Paul

Pradyut Pokuri於 2013年9月20日星期五UTC+8上午2時58分18秒寫道:

Pradyut Pokuri

unread,
Sep 25, 2013, 8:23:15 PM9/25/13
to ang...@googlegroups.com
This worked out well for me Paul! Thank you so much for your help.

One final question, where do you do call $scope.apply() ?

The reason I ask is that for me:
$rootScope.$broadcast('incomingData', event);
Will not have 'incomingData' all the time. The broadcast name is different, so I have many different handlers for each event type. 

Now I will have to call $scope.apply in each handler instead of once, I was wondering if you had that same problem?

If not thanks for everything!

-
Prad

On Saturday, April 27, 2013 12:36:18 PM UTC-5, Paul Liu wrote:

Paul Liu

unread,
Sep 25, 2013, 9:58:13 PM9/25/13
to ang...@googlegroups.com
Hi Prad,

I use "incomingData" for all the Sockjs inbound data. I don't think $scope.apply is needed in the way that I structured the code.

I do have different "type" of data in those socket.payload. I process them after JSON.parse(socket.payload). 

Best Regards
Paul

 

Pradyut Pokuri於 2013年9月26日星期四UTC+8上午8時23分15秒寫道:

Anton U

unread,
Jul 3, 2014, 7:47:22 AM7/3/14
to ang...@googlegroups.com
please show me how to use the code given by you? Are there examples of calls?

четверг, 19 сентября 2013 г., 22:58:18 UTC+4 пользователь Pradyut Pokuri написал:

Pradyut Pokuri

unread,
Jul 10, 2014, 11:01:01 AM7/10/14
to ang...@googlegroups.com
Hi Anton take a look at Paul's code frm 9/9/13
That's what I used to make it work.


Reply all
Reply to author
Forward
0 new messages