2012-06-03 15 views
8

Mi script nodeNo.js lee las filas de una tabla en la base de datos 1, procesa y escribe las filas en la base de datos 2.¿Cuál es una buena forma de salir de un script node.js después de "se ha hecho todo"

La secuencia de comandos debe salir después de que todo está hecho.

¿Cómo puedo saber si todo está hecho y salir del nodo?

Si tengo una función de devolución de llamada de esta manera:

function exit_node() { 
    process.exit(); 
} 

(Editar: en el ínterin se hizo evidente que process.exit() podría también ser reemplazado por db.close() - pero esto no es La pregunta es en qué momento exactamente para hacer esto, es decir, cómo y dónde ejecutar esta devolución de llamada.)

Pero no es fácil de adjuntar en algún lugar. Después de la última lectura de db1, no es correcto, porque el procesamiento y la escritura todavía tienen que suceder.

Adjuntarlo a la escritura en db2 no es fácil, porque debe adjuntarse después de la última escritura, pero cada escritura es independiente y no sabe si es la última escritura.

También podría ocurrir teóricamente, que la última escritura haya terminado, pero otra escritura anterior todavía se esté ejecutando.


Edit: Lo siento, puedo ver la explicación de la pregunta no es completa y probablemente confuso, pero algunas personas todavía entendido y hay buenas respuestas a continuación. Continúa leyendo los comentarios y las respuestas, y debería darte una idea completa.


Editar: Podría pensar en algún mecanismo de "bloqueo" del controlador. Las diferentes partes de la secuencia de comandos agregan bloqueadores al controlador para cada "trabajo" abierto y los liberan una vez que el trabajo finaliza, y el controlador sale del script cuando ya no hay bockers presentes. Tal vez async podría ayudar: https://github.com/caolan/async

También me temo que esto explotaría el código y la lógica irracional.

+0

No entiendo su pregunta. El nodo * no * sale cuando todo está hecho. Una vez que haya más llamadas asíncronas en progreso, una vez que haya terminado de procesar el último registro que haya leído y todas sus escrituras se hayan completado, entonces Node saldrá por sí mismo; no tienes que hacer nada especial. –

+6

@JoeWhite Muchos módulos de bases de datos mantendrán abierta una conexión, manteniendo el proceso en funcionamiento. Creo que la pregunta (corrígeme si me equivoco, SHernandez) es cómo saber cuándo se hace el Nodo con todo lo relacionado con la base de datos Async IO, para que pueda saber cuándo cerrar la conexión DB permitiendo que el proceso salga. –

+2

El nodo no saldrá hasta que haya una o más devoluciones de llamada en espera o emisores de eventos activos. Como @BrandonTilley mencionó, algunos de los módulos DB mantienen la conexión DB abierta (eso es EventEmitter), por lo que debe cerrarla una vez que haya terminado con sus consultas. Por lo tanto, en la devolución de llamada de la consulta se escribe algo como 'db.close' (ver documentos), los resultados del proceso y el nodo saldrá solo (sin que usted llame a' process.exit'). – elmigranto

Respuesta

3

Aunque usando un contador podría ser tentador (idea simple, de fácil implementación), que va a contaminar el código con la lógica no relacionado.

db1.query(selector, function(err, results) { 
    db1.close(); 

    // let's suppose callback gets array of results; 
    // once all writes are finished, `db2.close` will be called by async 
    async.forEach(results, processRow, db2.close); 
}); 

// async iterator 
function processRow(row, cb) { 
    // modify row somehow 
    var newRow = foo(row); 

    // insert it in another db; 
    // once write is done, call `cb` to notify async 
    db2.insert(newRow, cb); 
} 

Aunque, utilizando process.exit aquí se siente como C++ new sin delete para mí. Mala comparación tal vez, pero no puede evitarlo :)

+0

¿Qué significa el selector? (Primer parámetro de db1.query)? – SHernandez

+0

@SHernandez Usted ** selecciona ** filas de alguna manera, ¿verdad? Si es Postgres, 'selector' sería una cadena (' SELECT now(); 'o algo así). Si es otra base de datos, el selector sería otra cosa. Lo mismo con 'newRow' en la inserción. De todos modos, esa fue una idea en mi respuesta, no un código real. – elmigranto

7

Las dos opciones principales son:

  1. utilizar un módulo de coordinación procesamiento asíncrono como async (como usted ha mencionado).
  2. mantener bajo su propio recuento de escrituras pendientes y salga cuando el recuento de cuenta llega a 0.
+0

Me gusta no 2. ¿No debería ser un problema aumentar y disminuir el mismo contador global de diferentes rutinas de devolución de llamada en paralelo? Aumento y disminución puede ocurrir en cualquier momento desde diferentes partes de la aplicación, ¿puedo hacer esto en el nodo? – SHernandez

+0

No hay ningún problema con la contención, ya que si bien el procesamiento es asincrónico, aún tiene un único subproceso. – JohnnyHK

+0

@SHernandez nada en el nodo en sí es paralelo. No hay dos líneas de código en todo su proyecto, que podrían estar ejecutándose al mismo tiempo. Por lo tanto, no hay necesidad de serialización de acceso. – elmigranto

10

JohnnyHK da buenos consejos; excepto que Node.js ya hace la opción 2 por ti.

Cuando ya no hay E/S, temporizadores, intervalos, etc. (no se espera más trabajo), el proceso finalizará.Si su programa no sale automáticamente después de que todo su trabajo está hecho, entonces usted tiene un error. Quizás olvidó cerrar una conexión de base de datos o clearTimeout() o clearInterval(). Pero en lugar de llamar al process.exit(), puede aprovechar esta oportunidad para identificar su fuga.

+0

JasonSmith, es al revés, traté de explicar en la pregunta. Debido a que utilizo devoluciones de llamada, ninguno de ellos sabe cuál es el último. Y tan pronto como sé, cuando todo está hecho, puedo cerrar la conexión de DB o salir o lo que sea. Pero esa fue la razón de mi pregunta en primer lugar. – SHernandez

+2

esto es :), gracias, 'si su programa no sale automáticamente después de que todo su trabajo está hecho, entonces usted tiene un error' – Rabea

Cuestiones relacionadas