2012-03-10 18 views
7

que tiene un código comoejecución secuencial en Node.js

common.findOne('list', {'listId': parseInt(request.params. istId)}, function(err, result){  
    if(err) { 
    console.log(err); 
    } 
    else { 
    var tArr = new Array();    
    if(result.tasks) { 
     var tasks = result.tasks; 
     for(var i in tasks) { 
     console.log(tasks[i]); 
     common.findOne('tasks', {'taskId':parseInt(tasks[i])}, function(err,res){ 
      tArr[i] = res;  
      console.log(res);      
     });      
     } 
     console.log(tArr); 
    }    
    return response.send(result); 
    } 
}); 

No se ejecuta de forma secuencial en Node.js por lo que obtener una matriz vacía al final de la ejecución. El problema es que ejecutará primero y luego ejecutar console.log(tArr);

common.findOne('tasks',{'taskId':parseInt(tasks[i])},function(err,res){ 
     tArr[i] = res;  
     console.log(res);           
});      

¿Hay algún error en mi código, o cualquier otra forma de hacer esto. Gracias!

Respuesta

13

Como probablemente sepa, las cosas se ejecutan de forma asincrónica en node.js. Por lo tanto, cuando necesite que las cosas funcionen en un orden determinado, debe hacer uso de una biblioteca de control o implementarla básicamente usted mismo.

le recomiendo que eche un vistazo a async, ya que le permitirá fácilmente que para hacer algo como esto:

var async = require('async'); 

// .. 

if(result.tasks) { 
    async.forEach(result.tasks, processEachTask, afterAllTasks); 

    function processEachTask(task, callback) { 
    console.log(task); 
    common.findOne('tasks', {'taskId':parseInt(task)}, function(err,res) { 
     tArr.push(res); // NOTE: Assuming order does not matter here 
     console.log(res); 
     callback(err); 
    }); 
    } 

    function afterAllTasks(err) { 
    console.log(tArr); 
    } 
} 

Las principales cosas que vemos aquí es que processEachTask se llama a cada tarea, en paralelo , entonces la orden no está garantizada Para marcar que la tarea se ha procesado, llamará al callback en la función anónima al findOne. Esto le permite realizar más trabajos asincrónicos en processEachTask, pero aún así se las arregla para indicar cuándo termina. Cuando se completa cada tarea, llamará al afterAllTasks.

Para ver todas las funciones de ayuda que proporciona, ¡es muy útil!

+0

en lugar de iterar sobre result.tasks ¿Podemos iterar un objeto de resultado (JSON)? Lo intenté pero me da un error como el Objeto # no tiene el método 'foreach' y también veo todas las funciones auxiliares de async pero no hay función para la iteración de objetos. –

+0

Puede iterar sobre una matriz que está en JSON ... parece que tenía un objeto, por lo que no puede iterar sobre eso. Si necesita ayuda con el manejo del objeto JSON, publique una nueva pregunta. – staackuser2

+3

La pregunta pide "Ejecución secuencial en node.js". Esto hace exactamente lo opuesto. De ahí mi voto abajo –

5

que he creado recientemente una simple abstracción llamada "wait.for" para llamar a funciones asíncronas en el modo de sincronización (a base de fibras): https://github.com/luciotato/waitfor

Usando wait.for y asíncrono su código será:

var wait = require('waitfor'); 

... 

//execute in a fiber 
function handleRequest(request,response){ 
    try{ 
    ... 
    var result = wait.for(common.findOne,'list',{'listId': parseInt(request.params.istId)}); 
    var tArr = new Array();    
    if(result.tasks) { 
      var tasks = result.tasks; 
      for(var i in tasks){ 
       console.log(tasks[i]); 
       var res=wait.for(common.findOne,'tasks',{'taskId':parseInt(tasks[i])}); 
       tArr[i] = res;  
       console.log(res);      
      } 
      console.log(tArr); 
      return response.send(result); 
    }; 
    .... 
    } 
    catch(err){ 
     // handle errors 
     return response.end(err.message); 
    } 
}; 


// express framework 
app.get('/posts', function(req, res) { 
    // handle request in a Fiber, keep node spinning 
    wait.launchFiber(handleRequest,req,res); 
    }); 
Cuestiones relacionadas