Client can receive events but can't emit - javascript

I have my client set up like this:
var socket = io();
socket.on('thing', function(socket){
console.log('A user connected: ' + socket.data);
});
function sendThing(){
var data = document.getElementById('myInput').value;
console.log(data)
socket.emit('message', { message: data });
}
I can receive events just fine, I have my server emit an event and it logs out fine:
io.on('connection', (socket) => {
io.emit('thing', { data: 'thisisathing' });
});
Edit: my on.message function:
io.on('message', (socket) => {
console.log(socket.message);
});
But my server never receives a message because the emit on the client side does not fire. Socket exists and I get no errors.
How do I fix this?

Try nesting your listener within your connection function like:
io.on('connection', (socket) => {
socket.on('message', (socket) => {
console.log(socket.message);
});
});
as described in the docs

I think you have to listen to message inside the connection :
io.on('connection', (socket) => {
socket.emit('thing', { data: 'thisisathing' });
socket.on('message', (data) => {
console.log(data.message);
});
});

Related

Why is the client not receiving the socket.io broadcast (rooms)?

My client is not receiving the broadcast sent to the room. If I replace socket.to(roomName).emit('join', currentUser); with socket.emit('join', currentUser); the client receives the broadcast, but I'd like to use rooms here. Any help would be greatly appreciated.
app.js
// Game
app.get('/game', (req, res) => {
const cookies = req.cookies;
const currentUser = cookies['current_user'];
const roomName = cookies['room_name'];
if (roomName) {
res.render('pages/game', {
room: roomName
});
io.of('/game').on('connection', socket => {
console.log('a user connected');
socket.on('disconnect', () => {
console.log('user disconnected');
});
socket.join(roomName);
socket.to(roomName).emit('join', currentUser);
});
} else {
res.redirect('/login');
}
});
game.ejs
const socket = io("/game");
socket.on('join', function(user) {
console.log(`${user} joined`);
});
Also, could I replace this:
if (roomName) {
// stuff
} else {
// other stuff
}
with this:
if (!roomName) {
// other stuff
return;
}
// stuff
According to the documentation, if you use socket.to('room').emit(...) instead of io.in('room').emit(...), it will be broadcasted to all sockets in the room except the sender. That's where your problem lies.
The reason socket.emit(...) works is because you're sending it directly and only to the sender.
This emit cheatsheet is quite useful to figure out which combinations of io/socket and to etc affect where messages get sent to.

Socket.io call ack on connect event

Is there any way too utilize the ack argument on the connect event in Node.js? Something like this:
//client.js
socket.on('connect', (data) => {
console.log(data); // I want to print 'lol' here
});
//server.js
io.on('connect', (socket, ack) => {
ack('lol'); // TypeError: ack is not a function
});
Reference for ack: https://socket.io/docs/server-api/#socket-emit-eventname-args-ack
It doesn't look like the socket.connect() or socket.open() methods take an ack argument. I generally will emit a 'connected' event from the server once a connection from the client is established. You can receive this emission and add your behavior as needed.
server.js
io.on('connect', function(socket) {
socket.emit('connected');
});
client.js
socket.on('connected', function() {
console.log('Connected');
});
There is no specific ack data that you can send for the connect event. You can just .emit() a message to the client when the server receives the connect.
//client.js
socket.on('connect', () => {
console.log('client connected');
});
socket.on('welcome', function(data) {
console.log(data); // 'lol'
});
//server.js
io.on('connect', (socket) => {
// send welcome message upon connect
socket.emit('welcome', 'lol');
});

What Express websocket events exist?

I am wondering what websocket events exist So far I have only been using the ws.on('message') event, but I would like to use an event that is triggered when the connection is established and closed. I tried adding ws.on('connection'), but that didn't get triggered.
My code:
app.ws('/', function (ws, req) {
ws.on('message', function (textChunk) {
//do stuff
}
});
});
Do I need some client side programming to do this?
I tried adding this, but it didn't trigger when I connected from my client.
ws.on('request', function () {
console.log("request");
});
The function provided to app.ws is the one executed when a new websocket is opened. So use it this way:
app.ws('/', function (ws, req) {
console.log("New connection has opened!");
ws.on('close', function() {
console.log('The connection was closed!');
});
ws.on('message', function (message) {
console.log('Message received: '+message);
});
});
After looking at the source code for express-ws it looks like you can do the following.
var express = require('express');
var app = express();
var expressWs = require('express-ws')(app);
// get the WebsocketServer instance with getWss()
// https://github.com/HenningM/express-ws/blob/5b5cf93bb378a0e6dbe6ab33313bb442b0c25868/index.js#L72-L74
expressWs.getWss().on('connection', function(ws) {
console.log('connection open');
});
// ... express middleware
// ... websocket middle ware
app.ws('/', function(ws, req) {
ws.on('message', function(msg) {
console.log(msg);
});
});
app.listen(3000);
Old Response
There are the following:
close
error
message
open
https://developer.mozilla.org/en-US/docs/Web/API/WebSocket#Attributes
Okay I found one more event that actually triggers. Now if only I would find one that gets called once on open connection.
app.ws('/', function (ws, req) {
ws.on('close', function() {
console.log('close connection');
});
ws.on('message', function (textChunk) {
//do stuff
}
});
});

Connections are duplicationg in Socket.io

I'm developing a chat app, and the connections are duplicating.
In my route, I have:
exports.index = function (io) {
return function (req, res) {
var userId;
res.render('index', {
title: 'RandomChat.me',
test: 'test2'
});
io.sockets.on('connection', function (socket) {
userId = socket.id;
console.log("+++++++++++++++++++" + userId);
socket.emit('addUser', { userId: userId });
socket.room = 'General';
socket.join(socket.room);
socket.on('sendMessage', function (data) {
console.log(data.room);
// socket.broadcast.emit('receiveMessage', { data: data });
socket.broadcast.to(data.room).emit('receiveMessage', { message: data.message });
});
});
}
};
Client-side something like:
var socket = io.connect('http://domain.com:3000');
var userId;
socket.on('addUser', function(data) {
userId = data.userId;
console.log(userId);
});
socket.on('receiveMessage', function (data) {
console.log(data);
});
var room: "General";
var message: "Test";
socket.emit('sendMessage', { room : room, message: message });
console.log(userId + " " + message)
If I go to the app and check the console log, I see the userId, and when I reload the page, I see the same ID's twice, if I reload again, I see it 3 times and so on.
The same thing is happening in the node.js console.
So basically when connections/users are duplicated, the other users receive duplicate messages, as the sendMessage/receiveMessages functions are run more than once.
Help appreciated.
The problem is this line
io.sockets.on('connection', function (socket) {
You should not put these inside a request handler because its just wrong to add a connection handler for socket for each request. Try doing these outside the request handler and use the io object to emit/broadcast events to sockets from the request handler.
Using io.sockets.once('connection', function (data){}) instead of io.sockets.on('connection', function (data){}) fixed it. It doesn't try to recover a lost connection.

How to know when channel is subscribed/unsubscribed with socket.io

Just searched all the web to find how can I track inside node.js server when a channel is subscribed or unsubscribed. What I can do right know is the connect and disconnect bindings, but no clue how to do it with channels.
io.sockets.on('connection', function (socket) {
console.log("["+socket.id+"] Connected");
// handler to know when a socket subscribed a channel (*) ?
// handler to know when a socket unsubscribed a channel (*) ?
socket.on('disconnect', function () {
console.log("["+socket.id+"] Disconnect");
});
});
Is it possible?
You are looking for "socket.of('channelName')" ...
See Socket.io docs
SERVER:
var io = require('socket.io').listen(80);
var chat = io
.of('/chat')
.on('connection', function (socket) {
socket.emit('a message', {
that: 'only'
, '/chat': 'will get'
});
chat.emit('a message', {
everyone: 'in'
, '/chat': 'will get'
});
});
var news = io
.of('/news')
.on('connection', function (socket) {
socket.emit('item', { news: 'item' });
});
CLIENT:
<script>
var chat = io.connect('http://localhost/chat')
, news = io.connect('http://localhost/news');
chat.on('connect', function () {
chat.emit('hi!');
});
news.on('news', function () {
news.emit('woot');
});
</script>

Categories