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

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);
})

Related

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

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,
})
})
})

socket.io - stop receiving own emits

TL;DR - How to prevent client from receiving its own messages?
So I'm playing with socket.io after my experience with apollo and graphql.
My simple server looks like this:
io.on('connection', (socket) => {
console.log('New connection established.');
socket.on('disconnect', () => {
console.log('User disconnected.');
});
// Projects:
socket.on('join project', (data) => {
console.log(`User (${data.user.email}) join project with ID ${data.project.id}`);
socket.join(data.project.id);
});
socket.on('leave project', (data) => {
socket.leave(data.project.id);
});
socket.on('change field', (data) => {
console.log('Field was changed:', data);
const { project } = data;
socket.to(project.id).broadcast.emit('field changed', data);
});
});
I'm emitting something like this inside my application:
socket.emit('change field', {
project: {
id: 1,
},
value: 'Hello world',
usersEmail: 'example#email.com',
fieldName: 'description',
});
socket.on('field changed', (data) => {
// if (data.usersEmail === 'example#email.com') return; // This would stop from receiving own messages
console.log('CLIENT: field was changed!', data);
});
What I thought would happen is (due to the broadcast flag that I set up in the on('change field', ...)):
Clients A emits the message
Clients other than A receive the message
What is happening is a log inside other clients and client A itself, saying that the field was changed. Am I missing something?
I had the exact same problem. Couldn't (or didn't try hard enough) to find a setting for it, so instead just added this to my clients on page load:
document.windowid = Math.round(Math.random() * 1000000000000);
Then, add this to the message you emit in your client:
windowid: document.windowid
Then, when you accept data on the client, only do the action when windowid is not the same:
if (message.windowid != document.windowid)
It's not great and socket.io should take care of this issue, but this is the solution I used in my app :)

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!

"TypeError: Cannot read property 's' of undefined". What is the meaning of this in agenda.js?

This is the stack trace: This happens when I run the server.js file in my project. Also I couldn't find any explanation on the web. Can someone help with this error please?
E:\users\ashane\documents\visual studio 2015\Projects\ShowTracker\ShowTracker\node_modules\agenda\lib\agenda.js:341
if ( this._mdb.s.topology.connections().length === 0 ) { ^
TypeError: Cannot read property 's' of undefined
at Agenda._findAndLockNextJob (E:\users\ashane\documents\visual studio 2015\Projects\ShowTracker\ShowTracker\node_modules\agenda\lib\agenda.js:341:17) at jobQueueFilling (E:\users\ashane\documents\visual studio 2015\Projects\ShowTracker\ShowTracker\node_modules\agenda\lib\agenda.js:420:10) at processJobs (E:\users\ashane\documents\visual studio 2015\Projects\ShowTracker\ShowTracker\node_modules\agenda\lib\agenda.js:404:7)
at doNTCallback0 (node.js:417:9)
at process._tickCallback (node.js:346:13)
at Function.Module.runMain (module.js:469:11)
at startup (node.js:134:18)
at node.js:961:3
These are the only codes that are using angenda and "s" < as a string
var mongoConnectionString = "mongodb://127.0.0.1/agenda";
var agenda = require('agenda')({ db: { address: mongoConnectionString } });
var sugar = require('sugar');
var nodemailer = require('nodemailer');
// define an agenda job called send email alert.
agenda.define('send email alert', function (job, done) {
// what should happen when send email alert job is dispatched.
// When this job runs, name of the show will be passed in as an optional data object.
// Since we are not storing the entire user document in subscribers array (only references),
// we have to use Mongoose’s populate method.
Show.findOne({ name: job.attrs.data }).populate('subscribers').exec(function (err, show) {
var emails = show.subscribers.map(function (user) {
return user.email;
});
var upcomingEpisode = show.episodes.filter(function (episode) {
return new Date(episode.firstAired) > new Date();
})[0];
var smtpTransport = nodemailer.createTransport('SMTP', {
service: 'SendGrid',
auth: { user: 'hslogin', pass: 'hspassword00' }
});
// standard Nodemailer boilerplate for sending emails.
var mailOptions = {
from: 'Fred Foo ✔ <foo#blurdybloop.com>',
to: emails.join(','),
subject: show.name + ' is starting soon!',
text: show.name + ' starts in less than 2 hours on ' + show.network + '.\n\n' +
'Episode ' + upcomingEpisode.episodeNumber + ' Overview\n\n' + upcomingEpisode.overview
};
smtpTransport.sendMail(mailOptions, function (error, response) {
console.log('Message sent: ' + response.message);
smtpTransport.close();
done();
});
});
});
agenda.start();
agenda.on('start', function (job) {
console.log("Job %s starting", job.attrs.name);
});
agenda.on('complete', function (job) {
console.log("Job %s finished", job.attrs.name);
});
it works when .on('ready') function is present. Here is my example.
var Agenda = require('agenda');
var agenda = new Agenda({db: { address: 'localhost:27017/servicebox-dev'}});
matcher.matchProviders(agenda);
agenda.on('ready', function() {
agenda.every('5 seconds', 'match providers');
agenda.start();
});
In agenda.js, at line if ( this._mdb.s.topology.connections().length === 0 ), this._mdb is undefined.
The method Agent.prototype.database assigns to _mdb the returned db object from MongoClient.connect. So my guess is that the connect operation fails. Are you sure of your connection string?

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);
...
}
});

Categories