Node.js + AngularJS + socket.io: connect state and manually disconnect

后端 未结 2 1502
轻奢々
轻奢々 2021-01-01 03:37

I use nodejs with socket.io and angularjs on client. I picked up angular-socketio example from the Internet and added disconnect method to It.

Socket se

2条回答
  •  猫巷女王i
    2021-01-01 03:59

    The core of the problem in this (just like in most of the other cases) is that the on method is called asynchronously most of the time (good!) but also synchronously in some cases (bad!).

    When you call socket.disconnect() from your application (from within a controller which lives in the "angular context") it synchronously fires the disconnect event which then propagates into the on method which is designed to open the boundary into the angular context. But since you are already in the angular context, angular complains with the error you mentioned.

    Since this issue is specific to the disconnect call the best options here are to

    • make the disconnect asynchronous by using setTimeout or $timeout (with the invokeApply arg set to false), or
    • keep an internal flag that will tell you if you are in the disconnect phase, and in that case, skip the $apply

    Example code:

    angular.module('app')
      .factory('socket', ['$rootScope', function ($rootScope, $timeout) {
    
        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);
                }
              });
            })
          },
          disconnect: function () {
            $timeout(socket.disconnect, 0, false);
          },
          socket: socket
        };
    
      }]);
    

    or

    angular.module('app')
      .factory('socket', ['$rootScope', function ($rootScope) {
    
        var socket = io.connect(),
            disconnecting = false;
    
        return {
          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
        };
    
      }]);
    

提交回复
热议问题