Issue
I have created a custom async emitter to have a server -> client -> server
method.
However, it doesn’t work as expected. It emits the event, but does not run the callback.
With Socket.IO debugging enabled, I can see that the socket.io:socket
is logging that it is emitting the correct event.
Function code:
export async function asyncEmit<T>(
region: string,
socket: Server,
event: string,
data: {
id: any;
[k: string]: any;
}
): Promise<{ result: T; error: boolean }> {
return new Promise((resolve, reject) => {
socket.to(region).emit(event, data);
const cb = (res: { result: T; error: boolean }, ack: any) => {
ack();
if (res.error) {
reject(res.result);
}
socket.off(`${data.id}-${event}`, cb);
resolve(res);
};
socket.on(`${data.id}-${event}`, cb);
setTimeout(() => {
socket.off(event, cb);
reject('Timed out.');
}, 5000);
});
}
Some example code I’m using to run the function:
const res = await asyncEmit<{ statistics: { members: number } }>(
botRegion,
socket,
'statistics',
{ id: botId }
);
The Socket.IO client does receive the emit and does return data correctly.
What am I doing wrong, and how can I fix it?
Thanks!
Edit, client side code is:
this.socketio.timeout(5000).emit(
`${uuid}-statistics`,
{
result: { statistics: { members: guild.memberCount } },
error: false,
},
(data: any, err: any) => {
if (err) {
this.logger.error(err);
}
if (data) {
return;
}
}
);
It does time out and log socket.io-client:socket event with ack id 0 has timed out after 5000 ms +5s
However on the server-side:
socket.io:socket got packet {"type":2,"nsp":"/","id":0,"data":["......-statistics",{"result":{"statistics":{"members":35}},"error":false}]} +3s
socket.io:socket emitting event ["......-statistics",{"result":{"statistics":{"members":35}},"error":false}] +0ms
socket.io:socket attaching ack callback to event +0ms
socket.io:socket dispatching an event ["......-statistics",{"result":{"statistics":{"members":35}},"error":false},null] +0ms
is logged. I believe this is some issue with my event handler code, however I can’t pinpoint it.
Solution
I ended up rewriting my code to not use Socket.IO rooms, and to use a Map<string, Socket>
and get the socket from there, so I can use Socket.IO callbacks.
This may not be the best way, but it’s the only way I could think of.
Answered By – jackmerrill
Answer Checked By – Willingham (BugsFixing Volunteer)