sincronas programacion produccion nodejs node funciones ejemplos ejecucion controlar asincronia asincrona node.js

node.js - programacion - npm



¿Cómo evitar que Node.js se cierre mientras espera una devolución de llamada? (5)

Tengo un código como este:

var client = new mysql.Client(options); console.log(''Icanhasclient''); client.connect(function (err) { console.log(''jannn''); active_db = client; console.log(err); console.log(''hest''); if (callback) { if (err) { callback(err, null); } callback(null, active_db); } });

Mi problema es que el nodo termina inmediatamente cuando lo ejecuto. Imprime ''Icanhasclient'', pero no se llama a ninguno de los console.log dentro de la devolución de llamada.

(mysql en este ejemplo es node-mysql .

¿Hay algo que se pueda hacer para que node.js espere a que se complete la devolución de llamada antes de salir?


Basado en la respuesta de @ Todd, creé una línea. Inclúyalo en el comienzo de su script, y configure done = true cuando haya terminado:

var done = (function wait () { if (!done) setTimeout(wait, 1000) })();

Ejemplo:

var done = (function wait () { if (!done) setTimeout(wait, 1000) })(); someAsyncOperation().then(() => { console.log(''Good to go!''); done = true; });

¿Como funciona? Si lo expandimos un poco:

// Initialize the variable `done` to `undefined` // Create the function wait, which is available inside itself // Note: `var` is hoisted but `let` is not so we need to use `var` var done = (function wait () { // As long as it''s nor marked as done, create a new event+queue if (!done) setTimeout(wait, 1000); // No return value; done will resolve to false (undefined) })();


La devolución de llamada no está en cola

El nodo se ejecuta hasta que todas las colas de eventos estén vacías. Una devolución de llamada se agrega a una cola de eventos cuando una llamada como

emmiter1.on(''this_event'',callback).

ha ejecutado. Esta llamada es parte del código escrito por el desarrollador del módulo.

Si un módulo es un puerto rápido de una versión síncrona / de bloqueo, es posible que esto no ocurra hasta que se complete una parte de la operación y todas las colas se vacíen antes de que ocurra, permitiendo que el nodo salga silenciosamente.

Este es un error furtivo, que es posible que el desarrollador del módulo no se encuentre durante el desarrollo, ya que ocurrirá con menos frecuencia en los sistemas ocupados con muchas colas, ya que será raro que todos estén vacíos en el momento crítico.

Un posible detector de arreglo / error para el usuario es insertar un evento de temporizador especial antes de la llamada a la función sospechosa.


Mi solución fue crear instancias de EventEmitter y escuchar mi evento personalizado.

var eventEmitter = new process.EventEmitter();

luego llamé a eventEmitter.emit desde la devolución de llamada asíncrona:

client.connect(function (err) { eventEmitter.emit(''myevent'', {something: "Bla"}) });

Lo último en mi script fue el eventEmitter.on :

eventEmitter.on(''myevent'', function(myResult){ // I needed the result to be written to stdout so that the calling process could get it process.stdout.write(JSON.stringify(myResult)); });

El nodo esperará hasta que el controlador de eventos termine de ejecutarse.


Miré a la node-mysql y no vi una referencia al comando client.connect en la API. ¿Es esta la verdadera llamada que estás tratando de hacer (no tratar de ser quisquilloso aquí)? Independientemente, en mi humilde opinión, debe pensar más acerca de cómo se diseña Javascript, porque utiliza un paradigma de programación diferente a la mayoría de los otros lenguajes populares.

El primer problema que veo en su código es que no ha definido la devolución de llamada, por lo que en realidad no existe. Supongo que console.log (devolución de llamada) no está definido. Desde su código, la función anónima es la ''devolución de llamada'' para la función client.connect. Debe definir lo que está llamando ''devolución de llamada'' en un ámbito superior. Por ejemplo, definiré una función myCallback para que exista en el ámbito superior a la función anónima de client.connect. Puede ser útil buscar alcance de variable Javacscript.

var myCallback(err, response) { if (err) { console.log(''err:%s'',err); } else { console.log(''response:%s'',response); } } client.connect(err, function(response) { // this anonymous function is the callback to client.connect, the var // ''callback'' would be undefined. if (err) { myCallback(err); return; // Explicit call to return, else the lines below would run. } myCallback(null, response); });

En segundo lugar, si no llama explícitamente return en Javascript, la función continuará procesándose. Fui mordido por esto myself . Finalmente, Javascript ejecuta un bucle event-driven lo que significa que nunca esperará a que las funciones devuelvan un valor, por lo que tenemos todas estas devoluciones de llamada en primer lugar. Puede obligar a Javascript a comportarse de manera diferente, por ejemplo, utilizando un ciclo while hasta que una condición sea verdadera. Consulte la biblioteca ''async'' de caolan , para conocer las diversas estrategias de manipulación del ciclo de eventos. La principal desventaja del uso excesivo de estos métodos es que en realidad desperdicia ciclos / bloqueos de CPU cuando probablemente deba usar más devoluciones de llamada y simplemente vuelva a pensar cómo funcionan sus programas.


Puede emitir un setTimeout o un tiempo de espera recurrente con setInterval.

Si desea verificar las condiciones de salida, también puede hacer un tiempo de espera condicional:

(function wait () { if (!SOME_EXIT_CONDITION) setTimeout(wait, 1000); })();

Pon esto al final de tu código y la consola simplemente esperará ... y esperará ... hasta que quieras que se cierre.