2012-03-10 12 views
7

Ho codice comeesecuzione sequenziale in 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); 
    } 
}); 

Non viene eseguito sequenzialmente in node.js modo da ottenere un array vuoto al termine dell'esecuzione. Il problema è che sarà prima esecuzione console.log(tArr); e quindi eseguire

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

C'è qualche errore nel mio codice o qualsiasi altro modo per fare questo. Grazie!

risposta

13

Come probabilmente saprete, le cose vengono eseguite in modo asincrono su node.js. Quindi, quando è necessario che le cose vengano eseguite in un determinato ordine, è necessario utilizzare una libreria di controlli o implementarla autonomamente.

Consiglio vivamente di dare un'occhiata a async, come sarà facilmente permetterà di fare qualcosa di simile:

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

Le cose principali da vedere qui è che processEachTask viene chiamato con ogni compito, in parallelo , quindi l'ordine non è garantito. Per contrassegnare che l'attività è stata elaborata, chiamerai il numero callback nella funzione anonima dal findOne. Ciò consente di eseguire più lavori asincroni in processEachTask ma continua a indicare quando è terminato. Al termine di ogni attività, chiamerà quindi afterAllTasks.

Dai un'occhiata a async per vedere tutte le funzioni di aiuto che fornisce, è molto utile!

+0

invece di eseguire iterate su result.tasks è possibile iterare un oggetto risultato (JSON)? ho provato ma mi dà un errore come Object # non ha metodo 'foreach' e anche vedere tutte le funzioni di supporto di async ma non c'è alcuna funzione per l'iterazione dell'oggetto. –

+0

È possibile eseguire iterazioni su una matrice che si trova in JSON ... sembra che tu abbia avuto un oggetto, quindi non puoi eseguire un'iterazione. Se hai bisogno di aiuto per la gestione dell'oggetto JSON, pubblica una nuova domanda. – staackuser2

+3

La domanda richiede "Esecuzione sequenziale in node.js". Questo fa esattamente il contrario. Quindi il mio voto negativo –

5

Recentemente ho creato una semplice astrazione denominato "wait.for" per richiamare le funzioni asincrone in modalità di sincronizzazione (a base di fibre): https://github.com/luciotato/waitfor

Utilizzando wait.for e asincrone il codice sarà:

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