2015-04-27 15 views
17

In alcuni script Node.js che ho scritto, noto che anche se l'ultima riga è una chiamata sincrona, a volte non viene completata prima del nodo. js esce.Node.js socket.send() funzioni che non si completano prima dell'uscita

Non ho mai visto un'istruzione console.log non eseguita/completata prima di uscire, ma ho visto che alcune altre istruzioni non sono state completate prima di uscire e credo che siano tutte sincrone. Potevo capire perché il callback di una funzione asincrona non avrebbe funzionato, naturalmente, in questo caso.

Il codice in questione è uno ZeroMQ .send() chiamata in questo modo:

var zmq = require('zmq'); 
    var pub = zmq.socket('pub'); 

    pub.bindSync('tcp://127.0.0.1:5555'); 

    setInterval(function(){ 
     pub.send('polyglot'); 
    },500); 

Il codice qui sopra funziona come previsto ... ma se tolgo setInterval() e basta chiamare in questo modo:

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); 

... Quindi il messaggio non verrà consegnato - il programma apparentemente uscirà prima che la chiamata pub.send() venga completata.

Qual è il modo migliore per garantire che una dichiarazione venga completata prima di uscire in Node.js? I ganci di spegnimento funzionerebbero qui, ma temo che sarebbe solo mascherare il problema dal momento che non è possibile mettere tutto ciò che è necessario per garantire corre in un gancio di arresto.

Questo problema può anche essere dimostrato in questo modo:

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.'); 
    } 

Credo che questo sia un/problema serio legit perché un sacco di programmi solo bisogno di pubblicare messaggi e poi morire, ma come possiamo efficacemente garantire tutto i messaggi vengono inviati (anche se non necessariamente ricevuti)?

EDIT: One (potenziale) modo per risolvere questo problema è quello di fare:

socket.send('xyz'); 
socket.close(); // supposedly this will block until the above message is sent 
process.exit(0); 
+0

in base alla progettazione uno script sincrono verrà eseguito fino al completamento a meno di processo.exit() viene chiamato, quindi in questo caso dovrai mostrare del codice. Altrimenti sarà solo una supposizione di lavoro su qualcosa che potrebbe anche non essere vero. –

+2

Non è possibile garantire il completamento asincrono in un hook di chiusura. – SLaks

+1

potresti provare a metterlo in un setTimeout con 0? –

risposta

8

Tuffarsi zeromq.node, potete vedere quali Socket.send appena pushes your data to _outgoing:

this._outgoing.push([msg, flags]); 

... e poi calls _flush iff zmq.ZMQ_SNDMORE is unset:

this._flush(); 

Sembra _flush is actually doing the socket write. Se _flush() non riesce, it emits an error.

Edit:

Sto indovinando chiamando pub.unbind() prima di uscire, costringerà il _flush() di essere chiamato:

pub.unbind('tcp://127.0.0.1:5555', function(err) { 
    if (err) console.log(err); 
    process.exit(0); // Probably not even needed 
}); 
+0

Non penso che un'uscita "prematura" causerà il fallimento di _flush(). Niente sta fallendo, è solo che il mio processo node.js non sa che deve aspettare fino al completamento del codice zmq –

+0

Per favore vedi le mie modifiche - invece di un process.exit() lo stesso problema può sorgere se lanciamo un errore . –

0

Penso che la risposta più semplice è il metodo socket.send() è in Infatti asincrono ed è per questo che vediamo il comportamento che ho descritto nell'OP. La domanda quindi è: perché lo socket.send() deve essere asincrono? Potrebbe non esserci una versione bloccante/sincrona che potremmo usare invece per lo scopo inteso nell'OP? Potremmo avere socket.sendSync()? K ringrazia

Problemi correlati