我只想在我的webapp的一个部分使用socket.io。我使用socket.io的set('authorization',fn)来握手当前上下文(express session和page-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();
});
答案 0 :(得分:3)
Socket.io无法以connect() - >的方式工作disconnect() - >连接()。
创建单页应用程序时,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