Pibo
Pibo

Reputation: 2541

Socket emit to specific user

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

Answers (1)

Pibo
Pibo

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

Related Questions