2016-04-24 8 views
0

Ich würde gerne durch jeden der Schüler durchlaufen und dann zwei Abfrage ausführen, die die Ausführung dieser beiden Abfragen sollte synchronisiert werden, zuerst eine erste, dann seit der zweiten Abfrage hängt von der ersten ab.Foreach Async-Funktion in node.js

Ich habe einige Code geschrieben, aber es scheint nicht bei allen Arbeiten:

Student.find({ status: 'student' }) 
    .populate('student') 
    .exec(function (err, students) { 
     if (err) { 
      return res.status(400).send({ 
       message: errorHandler.getErrorMessage(err) 
      }); 
     } 

     _.forEach(students, function (student) { 
      async.waterfall(
       [ 
        function (callback) { 
         console.log('first ' + student.firstName); 
         Student.find({ "_id": student.id }, callback); 
        }, 
        function (student, callback) { 
         console.log('second '+ student[0].firstName); 
         WorksnapsTimeEntry.find({ 
          "student": { 
           "$in": student.map(function (el) { 
            return el._id 
           }) 
          } 
         }, callback); 
        } 
       ], 
       function (err, results) { 
        if (err) { 
         // do something 
        } else { 
         // results are the matching entries 
         console.log('third'); 
         var totalMinutes = 0; 
         var totalAvgLevelActivity = 0; 
         var counter = 0; 
         _.forEach(results, function (item) { 
          _.forEach(item.timeEntries, function (item) { 
           if (item.duration_in_minutes) { 
            totalMinutes = totalMinutes + parseFloat(item.duration_in_minutes[0]); 
           } 

           if (item.activity_level) { 
            totalAvgLevelActivity = totalAvgLevelActivity + parseFloat(item.activity_level[0]); 
            counter++; 
           } 
          }); 
         }); 

         var obj = {}; 
         obj.studentId = 'test'; 
         obj.firstName = 'test'; 
         obj.lastName = 'test'; 
         obj.municipality = 'test'; 
         obj.totalMinutes = totalMinutes; 
         obj.totalAvgLevelActivity = totalAvgLevelActivity/counter; 
         arrayReports.push(obj); 
         // console.log('not yet finished.'); 
        } 
       } 
      ); 
     }); 

     res.json(arrayReports); 
     console.log('finished.'); 

Wer eine Idee hat, wie erreiche ich diese Sache in Node.js

+0

erhalten Sie eine Ausgabe? – Joey

+0

Ja, ich kann sehen, Studenten Vornamen gedruckt, aber ich bin nicht sicher, wenn sie so gedruckt werden, dass der erste Student mit allem fertig sein muss, bis der zweite Student startet ... auch res.json (arrayReports) ist immer Null als natürlich wird es ausgeführt, bevor diese Queries in foreach beendet sind, gibt es eine Möglichkeit, dass ich warten kann, bis alle fertig sind, dann führe res.json() aus. –

+0

Ich nehme an, du verwendest den 'async.waterfall' falsch. Von jeder der Aufgabenfunktionen müssen Sie die nächste Funktion mit geeigneten Argumenten aufrufen – ayushgp

Antwort

2

mongoose promisified ist, Sie don‘ t muss async verwenden, um den Fluss noch lodash für ein einfaches forEach zu behandeln. Und Ihre Suche nach _id Anfrage ist nutzlos, Sie haben bereits ein Student Objekt:

Student.find({ status: 'student' }) 
    // .populate('student') // why this? 
    .then(function (students) { 
     // build an array of promises 
     var promises = students.map(function (student) { 
      return WorksnapsTimeEntry.find({ 
       "student": student._id; 
      }); 
     }); 

     // return a promise to continue the chain 
     return Promise.all(promises); 
    }).then(function(results) { 
     // results are the matching entries 
     console.log('third'); 
     var totalMinutes = 0; 
     var totalAvgLevelActivity = 0; 
     var counter = 0; 
     _.forEach(results, function (item) { 
      _.forEach(item.timeEntries, function (item) { 
       if (item.duration_in_minutes) { 
        totalMinutes = totalMinutes + parseFloat(item.duration_in_minutes[0]); 
       } 

       if (item.activity_level) { 
        totalAvgLevelActivity = totalAvgLevelActivity + parseFloat(item.activity_level[0]); 
        counter++; 
       } 
      }); 
     }); 

     var obj = {}; 
     obj.studentId = 'test'; 
     obj.firstName = 'test'; 
     obj.lastName = 'test'; 
     obj.municipality = 'test'; 
     obj.totalMinutes = totalMinutes; 
     obj.totalAvgLevelActivity = totalAvgLevelActivity/counter; 
     arrayReports.push(obj); 
     // console.log('not yet finished.'); 
     res.json(arrayReports); 
     console.log('finished.'); 
    }).catch(function(err) { 
     return res.status(400).send({ 
      message: errorHandler.getErrorMessage(err) 
     }); 
    }); 
+0

genial, nett, sauber und vor allem, bearbeitbar :) thnx –