2012-03-10 1 views
7

J'ai code commeexécution séquentielle dans 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); 
    } 
}); 

Il n'est pas exécutée de façon séquentielle dans Node.js si je reçois un tableau vide à la fin de l'exécution. Le problème est qu'il va d'abord exécuter console.log(tArr); puis exécutez

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

Y at-il une erreur dans mon code ou tout autre moyen de le faire. Merci!

Répondre

13

Comme vous le savez probablement, les choses s'exécutent de manière asynchrone dans node.js. Donc, quand vous avez besoin de faire fonctionner les choses dans un certain ordre, vous devez utiliser une bibliothèque de contrôle ou l'implémenter vous-même.

Je vous suggère fortement de jeter un oeil à async, car il vous permettra facilement de faire quelque chose comme ceci:

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

Les principales choses à voir ici est que processEachTask est appelée à chaque tâche, en parallèle , donc la commande n'est pas garantie. Pour marquer que la tâche a été traitée, vous appelez callback dans la fonction anonyme de findOne. Cela vous permet de faire plus de travail asynchrone dans processEachTask mais quand même réussi à signifier quand c'est fait. Lorsque chaque tâche est terminée, il appellera alors afterAllTasks.

Jetez un oeil à async pour voir toutes les fonctions d'aide qu'il fournit, c'est très utile!

+0

J'ai essayé mais il me donne une erreur comme l'objet # n'a aucune méthode 'foreach' et voit également toutes les fonctions auxiliaires d'async mais il n'y a aucune fonction pour l'itération d'objet. –

+0

Vous pouvez effectuer une itération sur un tableau qui est en JSON ... vous semblez avoir un objet, donc vous ne pouvez pas itérer dessus. Si vous avez besoin d'aide pour gérer l'objet JSON, postez une nouvelle question. – staackuser2

+3

La question demande "Exécution séquentielle dans node.js". Cela fait exactement le contraire. D'où mon vote négatif –

5

J'ai récemment créé une simple abstraction nommée "wait.for" pour appeler des fonctions asynchrones en mode de synchronisation (à base de fibres): https://github.com/luciotato/waitfor

En utilisant wait.for et async votre code sera:

Au lieu d'itérer sur result.tasks pouvons-nous itérer un objet résultat (JSON)?
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); 
    }); 
Questions connexes