Похоже, что вы пытаетесь сделать две вещи здесь: вы хотите асинхронно циклически проходить курсы / занятия / студенты / навыки и делать довольно длительный Evaluation.findOne
вызов.
Я рекомендую заменить некоторые или все ваши циклы for на async.forEach
. Вы также можете поместить блок Evaluation.findOne
в вспомогательную функцию, обернутую в Promise
, но, учитывая, что он помещается в lines
после выполнения, это необязательный ход.
Сделайте что-то вроде этого: итерация навыков теперь использует async.forEach, а построитель строк обещает.
function (courses) {
var lines = [];
for (var i = 0; i < courses.length; i++) {
var course = courses[i];
var sessions = course.sessions;
var students = course.students;
var skills = course.skills;
console.log('\nCourse : ' + course);
for (var j = 0; j < sessions.length; j++) {
var session = sessions[j];
console.log('\nSession : ' + session);
for (var k = 0; k < students.length; k++) {
var student = students[k];
console.log('\nStudent : ' + student);
skills.forEach(function(skill) {
console.log('\nSkill : ' + skill);
buildStudentLine(student, session, skill, course)
.then((line )=> {
lines.push(line);
})
.catch((error) => {
console.log(error);
})
});
}
}
}
return lines;
}
function buildStudentLine(student, session, skill, course) {
return new Promise((resolve, reject) => {
Evaluation
.findOne({
student_id: student._id,
session_id: session._id,
skill_id: skill._id
})
.exec(function (err, evaluated) {
var line = [];
line.push(course.name);
line.push(session.date);
line.push(student.firstname);
line.push(student.name);
if (evaluated) {
line.push(evaluated.name);
line.push(evaluated.mark);
} else {
line.push(skill.name);
line.push('Not Evaluated');
// possibly put this in here if you don't want the line to enter the lines array:
// reject('Not Evaluated');
}
resolve(line);
});
});
}