Creé un emisor asíncrono personalizado para tener un server -> client -> server .
Sin embargo, no funciona como se esperaba. Emite el evento, pero no ejecuta la devolución de llamada.
Con la depuración de Socket.IO habilitada, puedo ver que socket.io:socket está registrando que está emitiendo el evento correcto.
Código de función:
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); }); }Un código de ejemplo que estoy usando para ejecutar la función:
const res = await asyncEmit<{ statistics: { members: number } }>( botRegion, socket, 'statistics', { id: botId } );El cliente Socket.IO recibe la emisión y devuelve los datos correctamente.
¿Qué estoy haciendo mal y cómo puedo solucionarlo?
¡Gracias!
Editar, el código del lado del cliente es:
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; } } ); Se agota el tiempo de espera y registra socket.io-client:socket event with ack id 0 has timed out after 5000 ms +5s
Sin embargo, en el lado del servidor:
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] +0msestá registrado. Creo que este es un problema con mi código de controlador de eventos, sin embargo, no puedo identificarlo.
Terminé reescribiendo mi código para no usar las salas de Socket.IO, y para usar Map<string, Socket> y obtener el socket desde allí, para poder usar las devoluciones de llamada de Socket.IO.
Puede que esta no sea la mejor manera, pero es la única que se me ocurrió.
Las devoluciones de llamada con Socket.io son diferentes y generalmente se denominan funciones de reconocimiento.
Para implementar devoluciones de llamada, el remitente necesitaría agregar la función al último parámetro de la llamada socket.emit() .
Ejemplo:
Remitente
socket.emit("statistics", {test: "just a message"}, (response) => { console.log(response); // <-- should output "success" });Receptor
socket.on("statistics", (data, callback) => { console.log(data.test); // <-- should output "just a message" callback("success");//<-- this will return to the sender/emitter });Con tiempo de espera:
socket.timeout(5000).emit("statistics", {test: "just a message"}, (err, response) => { if (err) // the event was not acknowledged by the receiver in the delay given else console.log(response); // <-- output is "success" });Tenga en cuenta que el primer argumento de la devolución de llamada es el " error "
this.socketio.timeout(5000).emit( `${uuid}-statistics`, { result: { statistics: { members: guild.memberCount } }, error: false, }, (err: any, data: any) => { if (err) { this.logger.error(err); } if (data) { console.log(data);//<-- this is where your callback resolves to } } );Lado del servidor:
const cb = (res: { result: T; error: boolean }, ack: any) => { //do whatever you want with res if (res.error) { console.log("Error:",res.result); ack("Errorfrom server"); } socket.off(`${data.id}-${event}`, cb); console.log("Success:",res.result) ack("Success from server");//<--this callback will send back to the emitter };Edite su código de acuerdo con esta estructura y pruébelo.