socket io emit failed callback - callback

Is there any way to know socket io emit failed and success, something like ajax callback methods: onSuccess, onError?
For socket io emit i only find:
socket.emit('publish', {message:'test message'},function (data) {
alert("")})
This callback only be called when the server send an ack response.But it can not apply for this situation:
At the moment of emit message to server, there is bad network or lost connection, that means server not receive this message, so the client callback function is not called.
What I want is:
When I call the socket io emit, if it fails, I want to retry 3 times.

I know this is an old post, but just in case anyone is still having trouble with this.
var socket = new io.connect('http://localhost:3000', {
'reconnection': true,
'reconnectionDelay': 1000,
'reconnectionDelayMax' : 5000,
'reconnectionAttempts': 3
});
socket.on('connect_error', function() {
console.log('Connection failed');
});
socket.on('reconnect_failed', function() {
// fired only after the 3 attemps in this example fail
console.log('Reconnection failed');
});
More info here -> https://socket.io/docs/client-api/#manager-reconnectionAttempts-value

Related

What is the difference between emit() and send() in flask socketio? [duplicate]

What's the difference between these two?
I noticed that if I changed from socket.emit to socket.send in a working program, the server failed to receive the message, although I don't understand why.
I also noticed that in my program if I changed from socket.emit to socket.send, the server receives a message, but it seems to receive it multiple times. When I use console.log() to see what the server received, it shows something different from when I use socket.emit.
Why this behavior? How do you know when to use socket.emit or socket.send?
With socket.emit you can register custom event like that:
server:
var io = require('socket.io').listen(80);
io.sockets.on('connection', function (socket) {
socket.emit('news', { hello: 'world' });
socket.on('my other event', function (data) {
console.log(data);
});
});
client:
var socket = io.connect('http://localhost');
socket.on('news', function (data) {
console.log(data);
socket.emit('my other event', { my: 'data' });
});
Socket.send does the same, but you don't register to 'news' but to message:
server:
var io = require('socket.io').listen(80);
io.sockets.on('connection', function (socket) {
socket.send('hi');
});
client:
var socket = io.connect('http://localhost');
socket.on('message', function (message) {
console.log(message);
});
Simple and precise (Source: Socket.IO google group):
socket.emit allows you to emit custom events on the server and client
socket.send sends messages which are received with the 'message' event
TL;DR:
socket.send(data, callback) is essentially equivalent to calling socket.emit('message', JSON.stringify(data), callback)
Without looking at the source code, I would assume that the send function is more efficient edit: for sending string messages, at least?
So yeah basically emit allows you to send objects, which is very handy.
Take this example with socket.emit:
sendMessage: function(type, message) {
socket.emit('message', {
type: type,
message: message
});
}
and for those keeping score at home, here is what it looks like using socket.send:
sendMessage: function(type, message) {
socket.send(JSON.stringify({
type: type,
message: message
}));
}
socket.send is implemented for compatibility with vanilla WebSocket interface. socket.emit is feature of Socket.IO only. They both do the same, but socket.emit is a bit more convenient in handling messages.
In basic two way communication systems, socket.emit has proved to be more convincing and easy to use (personal experience) and is a part of Socket.IO which is primarily built for such purposes
https://socket.io/docs/client-api/#socket-send-args-ack
socket.send // Sends a message event
socket.emit(eventName[, ...args][, ack]) // you can custom eventName

Socket IO broadcast to each client with their socket id

I'm getting comfortable with socket.io. It really rocks.
I am aware that from the server, I can either:
Respond to a socket client:
socket.emit(event, data);
Broadcast to other clients:
socket.broadcast.emit(event, data);
Broadcast to all clients without distinction:
io.emit(event, data);
But what I'd like to do is to loop over the clients to emit to each of them, with their socket.id as a parameter:
io.emitEach(socket => socket.emit(event, dataWichDependsOn(socket.id)));
Can I achieve this?
I tried this:
io.of('/').clients((error, clients) => {
if (error) throw error;
return clients.forEach(clientId => {
io.to(clientId).emit(event, dataWichDependsOn(clientId));
})
}
Without success :( the message doesn't seem to be emited.
Object.keys(io.sockets.sockets).forEach((clientId)=>{
io.to(clientId).emit(event, dataWichDependsOn(clientId))
})

socket.io duplicate emit events on browser refresh

I'm running into an issue with my socket.io implementation and don't know how to solve it. I'm using pg_notify with LISTEN so when a certain value is modified in the db, it emits 'is_logged_in' to a certain client.
That in itself is working fine - my issue is when I refresh the page, socket.io disconnects the current socket_id, creates a new socket_id as usual, but when this happens, it's creating a second pgsql client instance and duplicating requests - fires the "logged_in" event 2x.
If I refresh the page again, and then manually fire the pg "logged_in" trigger, it will now emit 3 times etc. I have a leak.
const io = require('socket.io')();
const pg = require('pg');
io.on('connection', (socket) => {
const pgsql = new pg.Client({
(host, port, user, pass, db)
})
pgsql.connect()
pgsql.query("LISTEN logged_in");
pgsql.on('notification', function (data) {
socket.to(json.socket_id).emit('is_logged_in', { status:'Y' });
});
socket.on('disconnect', () => {
//pgsql.end();
});
});
I've tried killing the pgsql instance (in the socket.on disconnect) but for some reason the LISTEN stops working when I do that.
I've also tried moving the new pg.Client outside the io.on connection but when I refresh the page, the old socket_id disconnects, the new one connects, and it never executes the code to recreate the pg client.
Any ideas?
These are creating problems probably:
The pgsql instance is created on each socket connection request and is not being destroyed on disconnection
notification handler is not being removed on disconnection
I'm not much familiar with postgres, but I have worked extensively with socket. so, something like this should fix your issue:
const io = require('socket.io')();
const pg = require('pg');
const pgsql = new pg.Client({
(host, port, user, pass, db)
})
pgsql.connect();
io.on('connection', (socket) => {
pgsql.query("LISTEN logged_in");
const handler = function (data) {
socket.to(json.socket_id).emit('is_logged_in', { status:'Y' });
// You could also do pgsql.off('notification', handler) here probably
// or check if pgsql.once method is available as we need to call this handler only once?
}
pgsql.on('notification', handler);
socket.on('disconnect', () => {
pgsql.off('notification', handler);
//pgsql.end(); // Call it in server termination logic
});
});

It's possible to implement socket.io with ack, and if the server did not receive the ack, the server try again to emit the event?

It's possible to implement socket.io with ack , and if the server did not receive the ack, the server try again to emit the event?
socket.io uses TCP as the underlying transport which is a "reliable" transport. TCP will retry on it's own. The packet will be delivered unless the connection is permanently down. If the connection is down, what you really need is for the client to reconnect (which it will do eventually if the connection is actually down).
You can use socket.io's ACK feature and implement your own timeout to retry, but I don't think it will really buy you much because if the connection is working, then TCP will deliver it for you as soon as the connection allows. If TCP can't deliver it for you, then you really need to client to establish a new connection (which it will do eventually) and then when the new connection comes in is when you need to retransmit.
If you wanted to try your own retry, you could do it like this:
function delay(t) {
return new Promise(function(resolve) {
setTimeout(resolve, t);
});
}
function send(socket, msg, data, maxRetries, retryTime) {
maxRetries = maxRetries || 5;
retryTime = retryTime || 30 * 1000;
return write(socket, msg, data).catch(function() {
--maxRetries;
if (maxRetries >= 0) {
return delay(retryTime).write(socket, msg, data);
} else {
throw new Error("socket.io write failed after maxRetries")
}
});
function write(socket, msg, data) {
return new Promise(function(resolve, reject) {
let timer = setTimeout(reject, retryTime);
socket.emit(msg, data, function() {
clearTimeout(timer);
resolve();
});
});
}
}
And, the listener on the client for the message you are sending would have to reply appropriately to the ACK.
// client side
io.on('someMsg', function(data, fn) {
// process data here
console.log(data);
// call ACK function to send ack back
fn();
});

socket.emit() vs. socket.send()

What's the difference between these two?
I noticed that if I changed from socket.emit to socket.send in a working program, the server failed to receive the message, although I don't understand why.
I also noticed that in my program if I changed from socket.emit to socket.send, the server receives a message, but it seems to receive it multiple times. When I use console.log() to see what the server received, it shows something different from when I use socket.emit.
Why this behavior? How do you know when to use socket.emit or socket.send?
With socket.emit you can register custom event like that:
server:
var io = require('socket.io').listen(80);
io.sockets.on('connection', function (socket) {
socket.emit('news', { hello: 'world' });
socket.on('my other event', function (data) {
console.log(data);
});
});
client:
var socket = io.connect('http://localhost');
socket.on('news', function (data) {
console.log(data);
socket.emit('my other event', { my: 'data' });
});
Socket.send does the same, but you don't register to 'news' but to message:
server:
var io = require('socket.io').listen(80);
io.sockets.on('connection', function (socket) {
socket.send('hi');
});
client:
var socket = io.connect('http://localhost');
socket.on('message', function (message) {
console.log(message);
});
Simple and precise (Source: Socket.IO google group):
socket.emit allows you to emit custom events on the server and client
socket.send sends messages which are received with the 'message' event
TL;DR:
socket.send(data, callback) is essentially equivalent to calling socket.emit('message', JSON.stringify(data), callback)
Without looking at the source code, I would assume that the send function is more efficient edit: for sending string messages, at least?
So yeah basically emit allows you to send objects, which is very handy.
Take this example with socket.emit:
sendMessage: function(type, message) {
socket.emit('message', {
type: type,
message: message
});
}
and for those keeping score at home, here is what it looks like using socket.send:
sendMessage: function(type, message) {
socket.send(JSON.stringify({
type: type,
message: message
}));
}
socket.send is implemented for compatibility with vanilla WebSocket interface. socket.emit is feature of Socket.IO only. They both do the same, but socket.emit is a bit more convenient in handling messages.
In basic two way communication systems, socket.emit has proved to be more convincing and easy to use (personal experience) and is a part of Socket.IO which is primarily built for such purposes
https://socket.io/docs/client-api/#socket-send-args-ack
socket.send // Sends a message event
socket.emit(eventName[, ...args][, ack]) // you can custom eventName