2011-07-20 15 views
9

Después de jugar con Node.js y leer sobre async i/o & programación programada mucho Me quedan algunos signos de interrogación.¿Cómo funciona el ciclo de eventos Node.js?

en cuenta la (pseudo) siguiente código:

var http = require('http'); 

function onRequest(request, response) 
{ 
    // some non-blocking db query 
    query('SELECT name FROM users WHERE key=req.params['key']', function (err, results, fields) { 
     if (err) { 
      throw err; 
     } 
     username = results[0]; 
    }); 

    // some non-blocking db query 
    query('SELECT name FROM events WHERE key=req.params['key']', function (err, results, fields) { 
     if (err) { 
      throw err; 
     } 
     event_name = results[0]; 
    }); 

    var body = renderView(username, event_name, template); 
    res.writeHead(200, {'Content-Type': 'text/plain'}); 
    res.write(body); 
    res.end(); 
}; 

http.createServer(onRequest).listen(8888); 

// request A: http://127.0.0.1:1337/?key=A 
// request B: http://127.0.0.1:1337/?key=B 

(creo) entiendo los conceptos básicos del ciclo de eventos; Con libev, Node.js crea un bucle de eventos que sondea (epoll/kqueue/...) un conjunto de descriptores de archivos para ver si se desencadenan eventos (nueva conexión, escritura, datos disponibles, etc.). Si hay una nueva solicitud, el bucle de evento llama a la función anónima pasada a createServer. Lo que no entiendo es lo que sucede después:

1) Para ejecutar las consultas al mismo tiempo, el controlador db debe tener algún tipo de subprocesamiento/grupo de conexiones, ¿verdad?

2) En el alcance de una solicitud: ¿Qué sucede después de enviar dos consultas? no se puede llamar a renderView porque las consultas aún no han regresado. ¿Cómo esperamos a que vuelvan las consultas? ¿Debería mantener el recuento de las devoluciones de llamada pendientes de ser activadas antes de continuar? El pensamiento básico que tuve fue;

onRequest -> ejecutar código asíncrono -> esperar devolución de llamada -> construir respuesta. La espera en este caso sería un bloqueo, por lo que necesitaría generar un hilo para cada onRequest. ¿Cómo se realiza la "espera de las devoluciones de llamada antes de construir la respuesta"?

3) ¿Cómo informa el controlador db al bucle de evento que se ha realizado y se debe invocar la devolución de llamada para los resultados de la consulta?

4) ¿Cómo ejecuta el bucle de evento la devolución de llamada dentro de la función anónima que creamos con el evento onRequest? ¿Es aquí donde entra el concepto de cierre donde el contexto se "guarda" en la función de devolución de llamada?

4) Ahora que tenemos los resultados de db, ¿cómo continuamos ejecutando las piezas renderView/res.write/res.end?

+0

te conocen que el código es de libre acceso, ¿derecho? ¿Has intentado leer el código y has encontrado un lugar en el cuello de botella? – jcolebrand

Respuesta

6

Run parrallel patrón de código asíncrono:

'esperar para el resultado de las dos funciones asíncronas' que puede hacer: tanto en las llamadas asíncronas devoluciones de llamada de verificación tanto de resultados y si todo listo, llame a su DoSomethingWithTwoDependantResults.

En su ejemplo es probable que necesite para ejecutar consultas de forma secuencial:

query(sql1, function(sqlres1) { 
    query(sql2, function(sqlres2) { 
     writeResultUsingDataFrom(sqlres1, sqlres2); 
    } 
}); 

su código original, modificado para ejecutar dos consultas en paralelo:

function writeReply(res, template, username, event_name) 
{ 
    var body = renderView(username, event_name, template); 
    res.writeHead(200, {'Content-Type': 'text/plain'}); 
    res.write(body); 
    res.end(); 
} 

function onRequest(request, response) 
{ 
    // some non-blocking db query 
    query('SELECT name FROM users WHERE key=req.params['key']', function (err, results, fields) { 
     if (err) { 
      throw err; 
     } 
     username = results[0]; 
     if (username && event_name) 
      writeReply(res, template, username, event_name); 
    }); 

    // some non-blocking db query 
    query('SELECT name FROM events WHERE key=req.params['key']', function (err, results, fields) { 
     if (err) { 
      throw err; 
     } 
     event_name = results[0]; 
     if (username && event_name) 
      writeReply(res, template, username, event_name); 

    }); 
}; 
3

¿Has visto this? Todavía estoy entendiendo el asunto y no puedo responder tu pregunta en detalle, pero básicamente tienes razón sobre el grupo de conversaciones ... Ryan explica bastante en el video.

EDITAR: Y this one aproximadamente un año después, cuando entra en más detalles.

Cuestiones relacionadas