2016-04-24 86 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 –