2

我只想在我的 webapp 的一个部分使用 socket.io。我使用 socket.io 的 set('authorization', fn) 来握手当前上下文(表达会话和页面 ID)。这在我刷新当前页面时效果很好,但在路由由 $location.path(url) 处理时不起作用。

Socket.io 代码(视图控制器):

.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');
  });
  ...

路由代码(主控制器,首页):

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

路由当然也是安全的服务器端。

Socket.io 服务:

.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
  };
});

我也尝试过直接在控制器中使用 socket.io(无服务),结果相同。

控制台也没有给出任何错误。

一种解决方案是在整个应用程序中使用 socket.io,使用 emits 通信 page-id 等。但是当我在这个“视图页面”只需要 socket.io 时,这似乎是一种浪费。

编辑:这是出错的地方(不应该省略这个):

$scope.$on('$destroy', function (event) {
  // disconnect socket when leaving page
  socket.disconnect();
});
4

1 回答 1

3

Socket.io 不能以 connect() -> disconnect() -> connect() 的方式工作。

创建单页应用程序时,io 始终位于命名空间中,并且不会从 io.sockets 中删除套接字。因此,在第二次 connect() 时不会创建新的套接字。

查看 socket.io 客户端库中的第 93 行:

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

解决方案,添加“强制新连接”:

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

感谢shaunhusain指点我进行 Chrome 调试!

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

于 2013-07-22T07:56:19.017 回答