javascript - example - Las funciones Node.js socket.send() no se completan antes de salir
socket io tutorial (2)
En algunos scripts de Node.js que he escrito, observo que incluso si la última línea es una llamada sincrónica, a veces no se completa antes de que salga Node.js.
Nunca he visto que una sentencia console.log
no se ejecute / complete antes de salir, pero he visto que otras sentencias no se han completado antes de salir, y creo que todas son sincrónicas. Pude ver por qué la devolución de llamada de una función asíncrona no se activaría, por supuesto, en este caso.
El código en cuestión es una .send()
ZeroMQ .send()
como:
var zmq = require(''zmq'');
var pub = zmq.socket(''pub'');
pub.bindSync(''tcp://127.0.0.1:5555'');
setInterval(function(){
pub.send(''polyglot'');
},500);
El código anterior funciona como se esperaba ... pero si setInterval()
y simplemente lo llamo así:
var zmq = require(''zmq'');
var pub = zmq.socket(''pub'');
pub.bindSync(''tcp://127.0.0.1:5555'');
pub.send(''polyglot''); //this message does not get delivered before exit
process.exit(0);
... Entonces, el mensaje no se entregará: el programa se cerrará aparentemente antes de que pub.send()
llamada pub.send()
.
¿Cuál es la mejor manera de asegurar que una declaración se complete antes de salir en Node.js? Los ganchos de apagado funcionarían aquí, pero me temo que eso solo estaría enmascarando el problema, ya que no puede poner todo lo que necesita para asegurar que se ejecute en un gancho de apagado.
Este problema también se puede demostrar de esta manera:
if (typeof messageHandler[nameOfHandlerFunction] == ''function'') {
reply.send(''Success'');
messageHandler[nameOfHandlerFunction](null, args);
} else {
reply.send(''Failure''); //***this call might not complete before the error is thrown below.***
throw new Error(''SmartConnect error: no handler for ZMQ message sent from Redis CSV uploader.'');
}
Creo que este es un problema legítimo / serio porque muchos programas solo necesitan publicar mensajes y luego morir, pero ¿cómo podemos asegurarnos de que todos los mensajes sean enviados (aunque no necesariamente recibidos)?
EDITAR: Una forma (potencial) de arreglar esto es hacer:
socket.send(''xyz'');
socket.close(); // supposedly this will block until the above message is sent
process.exit(0);
Al bucear en zeromq.node , puedes ver lo que Socket.send
simplemente envía tus datos a _outgoing
:
this._outgoing.push([msg, flags]);
... y luego llama a _flush
iff zmq.ZMQ_SNDMORE no está configurado :
this._flush();
Parece que _flush
realidad está haciendo la escritura de socket . Si _flush()
falla, emite un error .
Editar:
Supongo que llamar a pub.unbind()
antes de salir, forzará que se _flush()
al _flush()
:
pub.unbind(''tcp://127.0.0.1:5555'', function(err) {
if (err) console.log(err);
process.exit(0); // Probably not even needed
});
Creo que la respuesta simple es que el método socket.send()
es de hecho asíncrono y es por eso que vemos el comportamiento que describí en el OP.
La pregunta entonces es: ¿por qué socket.send()
tiene que ser asíncrono? ¿No podría haber una versión de bloqueo / síncrono que podríamos usar en su lugar para el propósito previsto en el OP? ¿Podríamos tener socket.sendSync()
?