Node.js + Socket.io: Client not receiving message - javascript

I am building a very basic chat system between two clients. While the server can receive a message from the client, it cannot send the message to the client (the receiveMessage event is not triggered when the server sends the message to the client). Below is my code client-side:
$("#send-msg").submit(function(e) {
e.preventDefault();
socket.emit("sendMsg", [$("#msg-text").val(), chattingWith]);
});
socket.on("receiveMessage", receiveMsg);
function receiveMsg(data) {
console.log("received msg"); // NOT OUTPUTTED
}
Below is my code server-side:
var socket = io.connect();
var io = socket(server, { pingTimeout: 63000 });
io.sockets.on("connection", userConnect);
function userConnect(user) {
user.on("sendMsg", sendMsg);
function sendMsg(msgData) {
var msgContent = msgData[0];
var receiverId = msgData[1];
console.log("received message from " + receiverId); // ACTIVATED
io.to(receiverId).emit("receiveMessage", [msgContent, receiverId]);
}
}

I think you should change a little your code:
Client side (I assume that chattingWith is a unique room or chat id):
$("#send-msg").submit(function(e) {
e.preventDefault();
socket.emit("send message", $("#msg-text").val(), chattingWith);
});
socket.on("send Message", receiveMsg);
function receiveMsg(data) {
console.log(data); //An array should be an output
}
Server side code:
io.on('connection', function(socket){
socket.on('send message', function(data, id){
socket.join(id)
io.sockets.in(id).emit('sendMessage', {
data: data,
})
})
})

Related

Socket.io - Emitted message is not received by other clients

I'm trying to send a message through socket.io but cant see the message in other clients, below is my code. I can see the text when I log it in console on the keyup function but this message is never received by other clients
var socket = io.connect('http://localhost:3000');
editor.on('keyup', function(){
var word = { id: 'room', user: 'user', value: editor.getValue()}
io.sockets.emit('typedCode', word);
console.log(word.value);
return false;
});
socket.on('typedCode', function(word) {
console.log('The server has a message for you: ' + word);
})
This is the error that I have received:
io.sockets is the default server namespace for all connections. io.sockets.emit() is used to emit from the server out to all connected clients.
On the client, to emit, you want to use your instantiated connection:
socket.emit('typedCode', word);
I can't see your whole code, but try it with the code below
var socket = io('http://localhost:3000');
editor.on('keyup', function(){
var word = { id: 'room', user: 'user', value: editor.getValue()}
socket.emit('typedCode', word);
console.log(word.value);
return false;
});
socket.on('typedCode', function(word) {
console.log('The server has a message for you: ' + word);
})

Issue with socket.io updating component to show new message in chatroom

I am building a chat app with React, Node/Express and socket.io. I have my sockets successfully set to my express server via http.createServer. I have a listener on client and server listening for new messages coming into the chat room. Ideally, I want each instance of the chat to be updated when there is an additional message, like any chat room that ever existed :)
Now I have a successful listen between client and server. I know because of a console.log server-side. However, I am not re-rendering the chat component when I submit a new message from a different instance.
So my code in my client-side (again React) component is as follows and I am using the socket CDN with script tags in my index.html (script tags not shown):
Socket CDN here
var socket = io('')
So that is the socket you see client side :
componentDidMount() {
return axios.get(`api/messages`)
.then((result) => {
if (result.data.length) {
this.setState({
messages: [ ...this.state.messages, ...result.data]
} , () => {
console.log("The state after messages are mounted : ", this.state)
})
}
})
.catch((err) => { throw err})
socket.on('new message', msg => {
this.newMessage(msg);
})
};
newMessage(msg) {
this.setState({
messages: [...this.state.messages, msg]
}, () => {
this.setState({ message: '' })
return this.scrollToBottom()
});
};
onSubmitMessage(event) {
event.preventDefault();
const content = this.state.message;
const msg = {
content,
createdAt : new Date(),
userId : "one",
chatRoomId : "two"
}
axios.post(`api/messages/`, msg)
.then(() => {
this.newMessage(msg);
socket.emit('new message', msg); //HERE'S THE SOCKETS IN ACTION
})
};
Here is the server-side code Node/Express:
//in server.js
const io = new socketIo(server)
require('./socketEvents')(io);
const connections = [];
Then a separate file for my socket events
//in socketEvents.js
module.exports = (io) => {
io.on('connection', (socket) => {
console.log("Beautiful sockets are connected")
socket.once('disconnect', () => {
console.log("socket is disconnected");
});
//DOESN'T DO ANYTHING YET
socket.on('join global', (username) => {
socket.join(username);
console.log("New user in the global chat : ", username)
});
socket.on('new message', (msg) => {
console.log("The new message from sockets : ", msg);
socket.emit('new message', msg.content);
});
});
}
My sockets server side are linked up with the client. I'm just not seeing new messages in different instances. Is it because I'm not re-rendering after the server receives the message?
Thanks in advance, please let me know if you need me to clarify anything.
Cheers!
I figured it out... I'm going to leave this post up with a walkthrough in an attempt to help others who are having trouble with sockets. I may post a blog about it. Will update if I do.
So the code listens on the client side for a message to be sent inside of my onSubmitMessage function.
onSubmitMessage(event) {
event.preventDefault(); //prevents HTML <form> from going on its own post
const content = this.state.message;
//Create message object
const msg = {
content,
createdAt : new Date(),
userId : "one",
chatRoomId : "two"
}
//HERE'S THE IMPORTANT PART!!!
axios.post(`api/messages/`, msg)
.then(() => {
// wrapped in a promise, send a handler to server called
// ('new message') with the message object
this.newMessage(msg);
socket.emit('new message', msg);
})
.then(() => {
//Another promise then waits for the handler to come back from server
//*****IMPORTANT*************
//Then invoke newMessage function to get the post on all sockets
socket.on('message', (msg) => {
this.newMessage(msg);
})
})
};
Now on the server side this is what's happening:
// This is where the listener is for the client side handle
socket.on('new message', (msg) => {
// broadcast.emit will send the msg object back to client side and
// post to every instance expcept for the creator of the message
socket.broadcast.emit('message', msg);
});
SO the data path is (C) for client, (S) for server:
receive message object from user and -------->
(C)socket.emit('new message') -----> (S) socket.on('new message') -------> (S) socket.broadcast.emit('message') --------> (C)socket.on('message')
Back in the client side, I can invoke my newMessage function, which will set the message to state so I can display it.
I hope someone finds this useful! Surprisingly, this seems to go relatively unanswered on Stack. If anyone has any questions feel free to ask!

socket.io emit message only after page reload

I have a problem with socket.io. The client can emit message to server for connecting, but if I leave the connection and then try to reconnect, socket io doesn't emit the message ('joinPerformance'). Only if I refresh the page then I can emit messages.
#CLIENT
function loginSuccess(easyrtcid, noMedia) {
selfEasyrtcid = easyrtcid;
console.log('loginSuccess',selfEasyrtcid);
//arm socket events only once
if(!socket){
socket = easyrtc.webSocket;
streaming.armEvents(socket);
}
settings.isStarted=true;
if(typeof settings.bindings.loginSuccess==='function')
settings.bindings.loginSuccess(easyrtcid);
if(settings.isInitiator===true){
console.log('Telling server to start performance');
socket.emit('startPerformance', {performanceID: settings.performanceID});
}else{
console.log('Telling server to join performance');
socket.emit('joinPerformance', {performanceID: settings.performanceID});
}
}
#SERVER
socket.on('joinPerformance', function (data) {
console.log('joinPerformance', data);
if(validateData(data, socket))
onJoinPerformance(data, socket);
});
function onJoinPerformance(data, socket) {
console.log('Join performance', data.performanceID);
console.log('rooom info',socket.adapter.rooms[data.performanceID]);
if(!socket.adapter.rooms[data.performanceID] || !socket.adapter.rooms[data.performanceID][socket.id] )
socket.join(data.performanceID);
if (!streamingPerformances[data.performanceID]) {
console.log('No such performance is streaming');
error(socket, 'No such performance is streaming');
} else {
console.log('joined performance');
streamingPerformances[data.performanceID].activeViewers[data.userID] = data;
streamingPerformances[data.performanceID].activeViewersCount++;
socket.emit('joinedPerformance', streamingPerformances[data.performanceID]);
socket.broadcast.to(data.performanceID).emit('performanceState', streamingPerformances[data.performanceID]);
}
}

Socket.io - Sending data from a pusher stream to the client

I am struggling to send a stream of data being consumed via pusher-client-node to the client using Socket.IO.
I am receiving my data in Node.JS like this:
var API_KEY = 'cb65d0a7a72cd94adf1f';
var pusher = new Pusher(API_KEY, {
encrypted: true
});
var channel = pusher.subscribe("ticker.160");
channel.bind("message", function (data) {
//console.log(data);
});
My data, which comes in continuously, looks like that:
{ channel: 'ticker.160',
trade:
{ timestamp: 1420031543,
datetime: '2014-12-31 08:12:23 EST',
marketid: '160',
topsell: { price: '0.00007650', quantity: '106.26697381' }}
My Socket.IO code looks like this:
/**
* Socket.io
*/
var io = require("socket.io").listen(server, {log: true});
var users = [];
var stream = channel.bind("message", function (data) {
console.log(data);
});
io.on("connection", function (socket) {
// The user it's added to the array if it doesn't exist
if(users.indexOf(socket.id) === -1) {
users.push(socket.id);
}
// Log
logConnectedUsers();
socket.emit('someevent', { attr: 'value' } )
stream.on("newdata", function(data) {
// only broadcast when users are online
if(users.length > 0) {
// This emits the signal to the user that started
// the stream
socket.emit('someevent', { attr: 'value' } )
}
else {
// If there are no users connected we destroy the stream.
// Why would we keep it running for nobody?
stream.destroy();
stream = null;
}
});
// This handles when a user is disconnected
socket.on("disconnect", function(o) {
// find the user in the array
var index = users.indexOf(socket.id);
if(index != -1) {
// Eliminates the user from the array
users.splice(index, 1);
}
logConnectedUsers();
});
});
// A log function for debugging purposes
function logConnectedUsers() {
console.log("============= CONNECTED USERS ==============");
console.log("== :: " + users.length);
console.log("============================================");
}
I am quite new to Node.JS and Socket.IO and struggle to use my pusher stream in Node.JS. Therefore my question: How to connect my Socket.IO code with my Pusher code?
You need to use socket/io rooms ...
server:
var channel = pusher.subscribe("ticker.160"); //subscribe to pusher
//pass messages from pusher to the matching room in socket.io
channel.bind("message", function (data) {
io.to('ticker.160').emit('room-message', {room:'ticker.160', data:data});
});
...
io.on("connection", function (socket) {
...
socket.on('join', function(room){
socket.join(room);
});
socket.on('leave', function(room){
socket.leave(room);
});
});
client:
io.emit('join','ticker.160');
io.on('room-message', function(message){
switch(message.room) {
case 'ticker.160': return doSomething(message.data);
...
}
});

Socket io multiplayer game infrastructure

var connectionHandler = function(socket) {
var player = null;
socket.on('login', function(data) {
player = {
data: okeyServer.playerJoin(data),
socket: socket
};
socket.emit('welcome');
});
socket.on('info server', function(data) {
var info = okeyServer.Info();
socket.emit('info server', info);
});
socket.on('join game', function (data) {
var gameid = data.gameid;
var side = data.side;
okeyServer.playerJoinGame(player, gameid, side);
});
socket.on('disconnect', function () {
okeyServer.playerLeave(player);
io.sockets.emit('player leave', player);
});
}
I am trying to do a multiplayer game app with socket.io. When player connects, i want a 'login' message to be sent first. and i initialize the player variable for further use.
Other messages uses the player variable later.
How can i make sure client sent a 'login' message before making other requests.
I can check if player is null on every request where i need player but that seems ugly.
You could install the other listeners from within the login listener:
var connectionHandler = function(socket) {
var player = null;
socket.on('login', function(data) {
// If we already have a player, just return a `welcome` message.
if (player !== null) {
return socket.emit('welcome');
}
// Store player.
player = {
data: okeyServer.playerJoin(data),
socket: socket
};
// Emit welcome message.
socket.emit('welcome');
// Set up the rest of the listeners.
socket.on('info server', function(data) {
var info = okeyServer.Info();
socket.emit('info server', info);
});
socket.on('join game', function (data) {
var gameid = data.gameid;
var side = data.side;
okeyServer.playerJoinGame(player, gameid, side);
});
socket.on('disconnect', function () {
okeyServer.playerLeave(player);
io.sockets.emit('player leave', player);
});
});
};
This assumes that a login message is only ever emitted once by the client during the lifetime of the connection. If that's not the case, you need to make some changes.

Categories