2016-04-24 87 views
0

我想遍历每个学生,然后优先执行两个查询,这两个查询的执行应该是同步的,第一个是第一个,然后是第二个查询取决于第一个。node.js中的foreach异步函数

我已经写了一些代码,但它似乎并没有在所有的工作:

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.'); 

任何人有一个想法,我该如何实现这个东西的Node.js

+0

您是否得到任何输出? – Joey

+0

是的,我可以看到学生的名字打印出来,但我不确定他们是否以这种方式打印出来,第一个学生必须完成一切直到第二个学生开始......也res.json(arrayReports)始终为空当然,它是在foreach中的那些查询完成之前执行的,是否有任何方法可以等到所有完成后再执行res.json() –

+0

我想你正在使用'async.waterfall'错误。从每个任务函数中,你需要用适当的参数调用下一个函数 – ayushgp

回答

2

mongoose是promisified,你不”不得不使用async来处理流程,也不能使用forEach。并且您通过_id查找请求是无用的,您已经有一个Student对象:

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

真棒,好,干净,最重要的是,可行:) thnx –