2

I want to use socket.io only at one section of my webapp. I use socket.io's set('authorization', fn) for handshaking the current context(express session and page-id). This works great when I refresh the current page, but does not when routing is handled by $location.path(url).

Socket.io code(view controller):

.controller('ViewCtrl', function ($scope, $routeParams, $http, $location, socket) {
  socket.connect('', { query: 'id=' + $routeParams.id });
  socket.emit('msg', { data: 'key'}); //DEBUG
  socket.on('connect', function(){
    console.log('Socket connected');
  });
  socket.on('disconnect', function(){
    console.log('Socket disconnected');
  });
  ...

Routing code(main controller, frontpage):

if (data.owner == "yes") $location.path('/view/' + $scope.id());

Routing is of course secured server-side also.

Socket.io service:

.factory('socket', function ($rootScope) {
  var disconnecting = false;
  var socket = {};
  return {
    connect: function(url, query){
      disconnecting = false;
      socket = io.connect(url, query);
    },
    on: function(eventName, callback){
      socket.on(eventName, function(){
        var args = arguments;
        if(!disconnecting){
          $rootScope.$apply(function(){
            callback.apply(socket, args);
          });
        }
        else {
          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);
          }
        });
      })
    },
    disconnect: function(){
      disconnecting = true;
      socket.disconnect();
    },
    socket: socket
  };
});

I've also tried using socket.io directly in the controller(no service), same outcome.

The console does not give any errors either.

One solution is using socket.io for the whole app, communicating page-id, etc with emits. But this seem to be a waste when I only need socket.io at this "view-page".

EDIT: This is where it goes wrong(should not have omitted this):

$scope.$on('$destroy', function (event) {
  // disconnect socket when leaving page
  socket.disconnect();
});
7
  • Just adding that node does not output any socket.io handshake debugging messages, which is turned on. Commented Jul 21, 2013 at 21:48
  • 1
    Have you added console.log statements to your controller definition to be sure it's being instantiated (same with the factory)? Also maybe drop in some debugger; line so chrome inspector will break in the controller and factory to see that values are what you expect in each. Commented Jul 21, 2013 at 22:01
  • Yes, I've also tried debugging with console.log commands. Adding one above, and one below. Both outputting. I also checked that the socket var was saved(outputting the socket object to console). Though, my debugging skills stops there:/ Commented Jul 21, 2013 at 22:09
  • 1
    You may want to check out the info on chrome debugging tools to see if something else will help... sounds like a very particular problem so will probably be hard to find a direct answer:developers.google.com/chrome-developer-tools/docs/… Also watching the network tab while doing this stuff should reveal and calls to the server for ya. Commented Jul 21, 2013 at 22:12
  • Ok. That helps. I see no request in network console to /socket.io/nr/id when routing with $location, and socket.socket.connected is false. I'll poke around in the socket object to see if I find anything abnormal. Commented Jul 21, 2013 at 22:22

1 Answer 1

3

Socket.io does not work in the manner connect() -> disconnect() -> connect().

When creating a one page app, io is always in namespace and socket is not removed from io.sockets. Therefor a new socket is not created at second connect().

Look at line 93 in socket.io client library:

if (options['force new connection'] || !io.sockets[uuri]) {
  socket = new io.Socket(options);
}

Solution, add 'force new connection':

var socket = io.connect('', { 'force new connection': true, query: 'id=' + $routeParams.id });

Thanks to shaunhusain for pointing me to Chrome debugging!

Reference: https://github.com/LearnBoost/socket.io-client/issues/251

Sign up to request clarification or add additional context in comments.

1 Comment

By using force new connection when ui-route change and then again come back to main page and select the other device to view the livetrack it can created both connection and i got two sockets data how to dissconnect the socket when ui-route change

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.