MauirceA
MauirceA

Reputation: 321

Vue & Sockets: Handling sending messages back and forth

I have a simple implementation, or an attempt at one, of a messaging system just to show an alert of a message to different users. I'm using https://www.npmjs.com/package/vue-socket.io Vue Socket Io but it's just a socket.io. I am attempting to have the client subscribe to an event in mounted. The name is based on their userID. The problem is that my implementation below doesn't work to show the alerts. I can see the event being subscribed to in mount and I can see sending message console log in the server so I know that is getting fired but I don't see the alert being triggered by the emit(Chat_....

server:

io.on('connection', function(socket) {
    socket.on('sendMessage', function (data) {
       console.log("Sending message to" + data.user);
       socket.emit(`CHAT_${data.user}`, data.msg)
    });
 });

client:

On the client, the userIDSelf is a user ID that is passed in as a prop. It's the User's logged in ID and in mounted, they automatically subscribe to the a chat channel with their userid appended to it, like a custom channel.

mounted() {
    this.sockets.subscribe(`CHAT_${this.userIDSelf}`, (data) => {
         alert(data)
    });
}, 

there is a function sendMessage that takes the values from 2 inputs (not seen) in the template. You have to enter a user ID on who you want the message sent to and then another input with the actual message. These are sent over to the backend server listed above.

methods: {
  sendMessage() {
        this.$socket.emit('sendMessage', {user:  this.userIDReceiver, msg: this.message})
  },
}

Upvotes: 1

Views: 1105

Answers (1)

turbopasi
turbopasi

Reputation: 3625

I see a logical problem here. In your server code

io.on('connection', function(socket) {
  socket.on('sendMessage', function (data) {
    console.log("Sending message to" + data.user);
    socket.emit(`CHAT_${data.user}`, data.msg)
  });
});

the socket (User 123) which emitted sendMessage event to the server, will eventually also be the socket which will receive the emitted CHAT_456 event from the server. But User 123 socket only listens to CHAT_123 events. The socket is sending itself a message but doesn't receive it.


Possible Solutions

A - the room approach

Once a socket connects on the server, throw it in a room based on it's user id. This requires sending the userid to the server during connection, e.g. with a query parameter. In the client just add a token query parameter to the connection string like

const io = require('socket.io-client');
const socket = io("https://server-domain.com/?token=" + userid);

and through the connecting socket in a room (join) on the server side like

io.on('connection', function(socket) {
  const userid = socket.handshake.query.token;
  socket.join(userid);
});

then your socket sendMessage would work like this

/* ... server side */
socket.on('sendMessage', function (data) {
  console.log("Sending message to" + data.user);
  io.to(data.user).emit('chatMessage', data.msg);
});

B - the keep reference to the socket approach

Internally every socket has a socket id. Normally these are not exposed the user/clients. However you do have a unique user id. So let's keep a user id / socket instance - relation on the server side, so you can get a reference to the socket object for each corresponding user, using the user id.

The most basic example for it would be a in-memory store on the server side

let socketRefs = {};
io.on('connection', function(socket) {
  const userid = socket.handshake.query.token;
  socketRefs[userid] = socket;
});

then your socket sendMessage would work like this

/* ... server side */
socket.on('sendMessage', function (data) {
  console.log("Sending message to" + data.user);
  let targetSocket = socketRefs[data.user];
  targetSocket.emit('chatMessage', data.msg);
});

Upvotes: 1

Related Questions