Reputation: 2541
I found several questions on the same subject, and none of theme worked for me. I suppose that's because I'm missing something in the process:
I want to send a message to a specific user. I use:
"express": "^4.13.3"
"socket.io": "^1.3.7"
"socket.io-client": "^1.3.7"
"mongodb": "^2.2.2"
"mongoose": "^4.5.4"
Here is my code:
server (As you can see, I use mongoose to handle session):
const io = new SocketIo(server);
io.use(socketioJwt.authorize({
secret: configSocket.secret,
handshake: true
}));
// persistence store of our session
const MongoStore = mongoStoreFactory(session);
const sessionMiddleware = session({
store: new MongoStore({
mongooseConnection: mongoose.connection,
ttl: (1 * 60 * 60) // 1 hour
}),
secret: configSocket.secretSession,
httpOnly: true,
resave: false,
saveUninitialized: false,
// rolling: true,
// secure: true,
cookie: { maxAge: 86400000 }
});
app.use(sessionMiddleware);
...
socketRouter(io);
then the socketRouter function. I store the socketId of the user profile with mongo dataStore to aim the user with emit.
exports = module.exports = (io) => {
io.sockets.on('connection', (socket) => {
Users.findById(socket.decoded_token.sub, (err, user) => {
if (user) {
// if the user exists, save the socket Id in the user collection
Users.update({_id: user._id}, {$set: {socketId: socket.id}}, (err2, result) => {
// ------ PROTECTED ROUTES ------ //
// MOBILE CALLS
...
// DASHBOARD CALLS
socket.on('forceNotif', (data) => Notif.force(data, io, socket));
// ------------------------------ //
});
}
});
socket.on('disconnect', ()=> {
Users.update({_id: socket.decoded_token.sub}, {$set: {socketId: null}});
});
});
The function called by 'forceNotif'. Here I expect a different behavior. I want socket to send the value to a specific user (different from the one sending the request). I retrieve the socketId from MongoDb and it's exact. Then I want to use it for my purpose. Several different propositions are made on web. I tested the followings:
exports.force = (par, io, socket) => {
// retrieve the socket id of the user to aim
Users.findOne({_id: par.id}, {socketId: 1, pseudo: 1}, (err, res) => {
console.log('--------------------------------------------------');
console.log('err: ', err);
console.log('pseudo: ', res.pseudo);
console.log('socketId: ', res.socketId);
// emit the value to a specific user
// not working
io.sockets.to(res.socket).emit('notifExtUpdate', {val: 'TO'});
io.to(res.socket).emit('notifExtUpdate', {val: 'TO'});
io.broadcast.to(res.socket).emit('notifExtUpdate', {val: 'TO'});
socket.broadcast.to(res.socket).emit('notifExtUpdate', {val: 'TO'});
socket.to(res.socket).emit('notifExtUpdate', {val: 'TO'});
// working well, but not my purpose
io.emit('notifExtUpdate', {val: 'BROADCAST'});
socket.broadcast.emit('notifExtUpdate', {val: 'BROADCAST'});
});
};
I hope somebody can help me :-)
Upvotes: 2
Views: 1691
Reputation: 2541
So here the solution I found: the socket documentation says than "each socket automatically joins a room identified by the id". But for some reasons I still don't understand, when I emit in the following way (where the socketId is stored, retrieved and checked with mongoDb), nothing happens:
socket.broadcast.to(socketId).emit('blabla', msg);
But finally I joined manually the user to a personal room in the following way:
io.on('connection', (socket) => {
Users.findById(socket.decoded_token.sub, (err, user) => {
if (user) {
// create a room for every user
socket.join(user._id);
socket.on('exemple', (data) => functionExemple(data, io));
...
and then I can emit to a specific user in functionExemple like this (where the targetId is the _id of the user in the collection):
exports.functionExemple= (par, io) => {
returnEmit.to(targetId).emit('blabla', msg);
};
I hope it will help somebody :-)
Upvotes: 2