Improve this AngularJS factory to use with socket.io

后端 未结 13 1509
你的背包
你的背包 2020-12-07 08:42

I want to use socket.io in AngularJS. I found the following factory:

app.factory(\'socket\', function ($rootScope) {
    var socket = io.connect();
    retur         


        
相关标签:
13条回答
  • 2020-12-07 08:51

    I tried different ways but nothing worked as expected. In my app I'm using a socket factory in both the MainController and a GameController. When the user switches to a different view I only want to remove the duplicates events generated by the GameController and leave the MainController running so I cannot use a removeAllListeners function. Instead I discovered a better way to just avoid creating duplicates inside my socket factory:

    app.factory('socket', function ($rootScope) {
      var socket = io.connect();
    
      function on(eventName, callback) {
        socket.on(eventName, function () {
          var args = arguments;
    
          $rootScope.$apply(function () {
            callback.apply(socket, args);
          });
        });
    
        // Remove duplicate listeners
        socket.removeListener(eventName, callback);
      }
    
      function emit(eventName, data, callback) {
        socket.emit(eventName, data, function () {
          var args = arguments;
    
          $rootScope.$apply(function () {
            if (callback) {
              callback.apply(socket, args);
            }
          });
        });
    
        // Remove duplicate listeners
        socket.removeListener(eventName, callback);
      }
    
      return {
        on: on,
        emit: emit
      };
    }
    
    0 讨论(0)
  • 2020-12-07 08:51

    I tried with the above code in my AngularApp and found the events duplicating. With the same Example from @pootzko using the SocketIoFactory

    I have added a unSubscribe(even_name) inside the $destroy of the Controller, that will remove/clear the socketEventListner

    var app = angular.module("app", []);
    ..
    ..
    ..
    //Create a SocketIoFactory
    app.service('SocketIoFactory', function($rootScope){
    
        console.log("SocketIoFactory....");
        //Creating connection with server
        var protocol = 'ws:',//window.location.protocol,
            host = window.location.host,
            port = 80,
            socket = null;
        var nodePath = protocol+'//'+host+':'+port+'/';
    
        function listenerExists(eventName) {
            return socket.hasOwnProperty("$events") && socket.$events.hasOwnProperty(eventName);
        }
    
        return {
            connect: function () {
                socket = io.connect(nodePath);
                console.log('SOCKET CONNECTION ... ',nodePath);
            },
            connected: function () {
                return socket != null;
            },
            on: function (eventName, callback) {
                if (!listenerExists(eventName)) {
                    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);
                        }
                    });
                })
            },
            unSubscribe: function(listener) {
                socket.removeAllListeners(listener);
            }
        };
    });
    
    ..
    ..
    ..
    
    //Use in a controller
    app.controller("homeControl", ['$scope', 'SocketIoFactory', function ($scope, SocketIoFactory) {
    
      //Bind the events
      SocketIoFactory.on('<event_name>', function (data) {
    
      });
    
      //On destroy remove the eventListner on socketConnection
       $scope.$on('$destroy', function (event) {
            console.log('[homeControl] destroy...');
            SocketIoFactory.unSubscribe('<event_name>');
        });
    }]);
    
    0 讨论(0)
  • 2020-12-07 08:58

    I use something like the code below. socketsService is only instantiated once and I believe Angular takes care of GC the $on's

    If you don't like $broadcast/$on, there are some slightly more solid Message Bus implementations for Angular available...

    app.service('socketsService', ['$rootScope', function ($rootScope) {
        var socket = window.io.connect();
    
        socket.on('info', function(data) {
            $rootScope.$broadcast("info_received", data);
        });
    
        socket.emit('ready', "Hello");
    }]);
    
    app.controller("infoController",['$scope',
        function ($scope) {
            $scope.$root.$on("info_received", function(e,data){
                console.log(data);
            });
            //...
        }]);
    
    app.run(
        ['socketsService',
            function (socketsService) {
            //...
        }]);
    
    0 讨论(0)
  • 2020-12-07 08:59

    Instead of doing app.factory, create a service (singleton) like so:

    var service = angular.module('socketService', []);
    service.factory('$socket', function() {
        // Your factory logic
    });
    

    You can then simply inject the service to your app and use it in controllers as you would $rootScope.

    Here is a more complete example of how I have this set up:

    // App module
    var app = angular.module('app', ['app.services']);
    
    // services
    var services = angular.module('app.services', []);
    
    // Socket service
    services.factory('$socket', ['$rootScope', function(rootScope) {
    
        // Factory logic here
    
    }]);
    
    // Controller
    app.controller('someController', ['$scope', '$socket', function(scope, socket) {
    
        // Controller logic here
    
    }]);
    
    0 讨论(0)
  • 2020-12-07 08:59

    I was having the exact same problem of duplicate events after a browser refresh. I was using a 'factory', but switched to use a 'service'. Here's my socket.io wrapper:

    myApp.service('mysocketio',['$rootScope', 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);
                        }
                    });
                });
            }
        }
    
    }]);
    

    I use this service inside my controller and listen for events:

    myApp.controller('myController', ['mysocketio', function(mysocketio)
    {
        mysocketio.on( 'myevent', function(msg)
        {
            console.log('received event: ' + msg );
        }
    }]);
    

    Once I switched from using a factory to using a service, I don't receive duplicates after a browser refresh.

    0 讨论(0)
  • 2020-12-07 09:00

    create function in your service or factory like below.

    unSubscribe: function(listener) {
        socket.removeAllListeners(listener);
    }
    

    and then call in your controller under the "$destroy" event like below.

    $scope.$on('$destroy', function() {
        yourServiceName.unSubscribe('eventName');
    });
    

    that's solve

    0 讨论(0)
提交回复
热议问题