Gestisci più tabs (ma lo stesso utente) in socket.io

Sto avendo problemi con socket.io e non ho idea di come risolverlo. Ho un’app con un sistema di login con socket.io per gestire le interazioni dell’utente. Inoltre ho una matrice per gestire tutte le sessioni websocket attive. Questo array memorizza una coppia session.id => username.

I problemi iniziano quando un utente apre una nuova scheda con la stessa pagina (o una pagina diversa che utilizza la websocket). Ciò causa una voce di nome utente duplicata nell’array.

{id1, username} {id2, username} 

Quando il socket invia un messaggio all’utente, invia solo al primo ID di sessione dell’array, quindi solo una scheda riceve il messaggio.

Ho provato a cambiare l’ID del socket della nuova connessione in modo che corrisponda all’altro, ma non funziona.

 socket.id = sessionId of the other websocket; 

Penso che un’altra soluzione sia quella di inviare il messaggio a tutte le sessioni aperte, ma penso che non sia il modo migliore per farlo.

Grazie.

Sembra che potresti riferirti all’ID del socket nella tua domanda, non all’ID di sessione. Se si dispone di una sessione espressa è ansible utilizzare l’id di sessione, che sarà lo stesso indipendentemente dal numero di tabs aperte purché utilizzino lo stesso browser e non sia in modalità “privata”. Dai un’occhiata a questa domanda su come abilitare le sessioni in socket.io.

socket.io e sessione?

Aggiornamento: quando si salva l’ID di sessione, lo associ al nickname dell’utente e ai socket connessi. Quindi puoi scorrere ogni socket e inviare il messaggio. Qualcosa come il seguente:

 [ {sessionId: '12345', nickname: 'timmay!', socketIds: [1, 2, 3]}, {sessionId: '23456', nickname: 'pete', socketIds: [4, 5, 6]} ] 

Quando viene stabilita un’altra connessione, si inserisce il nuovo ID socket nell’array socketIds e, quando un utente si disconnette, si rimuove l’id.

Un’altra opzione potrebbe essere quella di consentire solo una scheda per utente per sessione. È ansible memorizzare un singolo socketId e quando un nuovo socket si connette per lo stesso utente, è ansible disconnettere il socket originale e utilizzare quello nuovo.

Puoi usare hash come quello:

 var sessionHash = {}; sessionHash['userName'] = socket; 

e controllare io.sockets.on('connection',..) se esiste un socket sotto quella chiave.

Se lo fa, puoi eseguire sessionHash['userName'].disconnect(); su di esso e salvare il socket nuovo di zecca.

So che è passato molto tempo da quando lo hai chiesto, ma solo 4 anni fa ho pubblicato un modulo per node js, express e socket.io che gestisce esattamente ciò che volevi. Controlla l’utilizzo e l’esempio, spero che troverai utile questo modulo!

È ansible installarlo tramite NPM socket.io.users Questo è un modulo nodo js per le applicazioni socket.io. Un utente per cliente.

Alcuni dei codici di utilizzo

 var express = require('express'); var app = express(); var server = require('http').createServer(app); var socketUsers = require('socket.io.users'); //.... socketUsers.Session(app);//IMPORTANT //... var rootIo = require('socket.io')(server); //default '/' as namespace. var chatIo = rootIo.of('/chat'); var rootUsers = socketUsers.Users; /* default '/' as namespace. Each namespace has IT's OWN users object list, but the Id of a user of any other namespace may has the same value if request comes from the same client-machine-user. This makes easy to keep a kind of synchronization between all users of all different namespaces. */ var chatUsers = socketUsers.Users.of('/chat'); // rootIo.use(socketUsers.Middleware());/*IMPORTANT but no errors if you want to skip it for a io.of(namespace) that you don't want the socket.io.users' support. */ chatUsers.use(socketUsers.Middleware()); chatUsers.on('connected',function(user){ console.log(user.id + ' has connected to the CHAT'); user.store.username = 'username setted by server side'; /*at the store property you can store any type of properties and objects you want to share between your user's sockets. */ user.socket.on('any event', function(data){ /*user.socket is the current socket, to get all connected sockets from this user, use: user.sockets */ }); chatIo.emit('set username',user.store.username); }); rootUsers.on('connected',function(user){ console.log('User has connected with ID: '+ user.id); }); rootUsers.on('connection',function(user){ console.log('Socket ID: '+user.socket.id+' is user with ID: '+user.id); }); rootUsers.on('disconnected',function(user){ console.log('User with ID: '+user.id+'is gone away :('); }); //...server.listen blabla.. 

La libreria interfonica può essere utilizzata per condividere e gestire una connessione socket.io.

 // Initialize socket.io on one tab var socket = io.connect('//yourwebsite.com/socketio'); // Initialize intercom on all tab var intercom = Intercom.getInstance(); intercom.bind(socket); // Listen to an event intercom.on('msgBroadcast', function(data){ console.log(data); }); // Emit an event intercom.emit('msgBroadcast', { socket: true, message: 'Hello all!' }); 

Potresti anche utilizzare i webworker condivisi di socketio