4

Warning: I am pretty new to coding and web development.

I am making an angular application that uses socket.io to communicate realtime events on a node (express) server to other clients. The problem I am having is that when I am in the application and switch routes from "/pb" to "/" then back again, the "init" socket event is being fired twice on the client side. From what I can tell, the client is emitting the "requestInit" event only once, and the server is responding by emitting the "init" event only once. However, the client is running the code in the socketio.on('init') function multiple times when I switch views.

For example: I will open the application and navigate to /pb, the console will log

connected to socket
recieved socket event from server: Init
initCount: 1 

Now when I navigate to "/" then back to "/pb", the console will log

recieved socket event from server: Init
initCount: 2
recieved socket event from server: Init
initCount: 1

For each time I switch views, the initCount gets higher, so if I switch back and forth 5 times, the initCount will log 5 times, starting at 5 and ending with 1.

So the socketio.on('init') function on the client side is being fired multiple times when I enter the view, and in backwards order. My original guess is that is has something to do with the socket not closing when I switch views, so when I come back, it receives an "init" event for each open socket. However, the socketio.on('connect') function only fires on the initial navigation to "/pb". I've been googling for hours and I am still not able to find out whats going on. Any help would be appreciated. Here is the cod that is giving me trouble.

Client:

var app = angular.module('MainApp', ['ngRoute']);

app.config(['$routeProvider', '$locationProvider', function ($routeProvider, $locationProvider){

    $routeProvider
        .when('/', {
            templateUrl: 'views/home.html',
            controller: 'HomeController',
            activeTab: 'home'
        })
        .when('/pb', {
            templateUrl: 'views/pb.html',
            controller: 'PbController',
            activeTab: 'pb'
        })
        .otherwise({
            redirectTo: '/'
        });

    $locationProvider.html5Mode(true);
}]);

// SocketIO factory
app.factory('socketio', ['$rootScope', function($rootScope){
    var socket = io.connect('http://localhost:3000');
    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);
                    }
                });
            });
        }
    };
}]);

app.controller('PbController', ['$scope', 'socketio', function ($scope, socketio){

     $scope.initCount = 0;
/*
    ~~~~~~~~~~ Socket events ~~~~~~~~~~~~~~~~
*/
    socketio.emit('requestInit');

    socketio.on('connect', function(){
        console.log('connected to socket');
    });

    socketio.on('init', function (){
        console.log("recieved socket event from server: Init");
        $scope.initCount += 1;
        console.log("init count: " + $scope.initCount);
    });
}]);

Server:

var pbServerController = function (io){

io.on('connection', function (socket){
    console.log("Client connected, new socket issued: "+socket.id);

    socket.on('requestInit', function(){
        console.log("sending Init socketio event");
        socket.emit('init');
    });
};

module.exports = pbServerController;

2 Answers 2

2

Not sure if you ever figured this out. If not you can destroy the socket listeners with the scope.

In your controller:

$scope.$on('$destroy', function() {
  socket.removeListener();
});
Sign up to request clarification or add additional context in comments.

Comments

0

If anyone still struggling with this issue. I had the same problem, I solved it by simply initializing the socket variable out of the factory and used the variable on all other controllers.

app = angular.module('movex', ['ui.router'])
socket = io.connect('http://localhost:3000');

I don't know if this is the right way or not but it solved the problem.

Comments

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.