Используйте asyn c await внутри функции отображения - PullRequest
0 голосов
/ 18 января 2020

В моем приложении Node Express я хочу получить все комментарии к уроку и изменить каждый комментарий, добавив поле fullname к каждому комментарию. Для получения полного имени пользователя я определил функцию findFullNameByUserId в UserController.js. Я использую findAllCommentsByLessonId() в CourseController.js следующим образом. Однако, когда я использую его, я всегда получаю пустой массив. Как я могу использовать findFullNameByUserId в findAllCommentsByLessonId(), чтобы к каждому объекту комментария можно было добавить поле fullname?

CourseController. js

findAllCommentsByLessonId: async (courseId,lessonId,callback) => {
    Course.find({_id: courseId}, function(err, course) {
      if (err) {
        callback(err, null);
      } else {
        const lesson = course[0].lessons.filter(l => l._id !== lessonId)
        const comments = lesson[0].comments.map( async c => {
          try{
            const name = await UserController.findFullNameById(c.user)
            return (
              {
                userId: c.user,
                name: name,
                content: c.content
              }
            )
          }
          catch(err){
console.log(err)
          }
        })

// console.log(comments) --> This always prints [{}]
        callback(null, comments)   
    }
    });
  }

UserController. js

module.exports = {
    findFullNameById: async (userId) => {
        await User.find({_id: userId}, function(err, user) {
            if (err) {
                console.log(err)
            } else {
                return  user[0].name+" "+( user[0].lname ? user[0].lname : "") 

            }
          });
    }
}

Ответы [ 3 ]

1 голос
/ 18 января 2020

in CourseController.js либо вы можете использовать async-await, либо вы можете использовать callback

asyn c -wait way:

findAllCommentsByLessonId: async (courseId,lessonId) => {
    let course = await Course.findOne({_id: courseId});
    if (course){
        let lesson = course.lessons.find(l => l._id == lessonId);
        let comments = [];

        for(let comment of lesson.comments){
               let name = await UserController.findFullNameById(comment.user);
               comments.push({userId: comment.user,name: name,content: comment.content});
        }
      return comments;
    }else{
      return [];
      }
  }

обратный вызов:

findAllCommentsByLessonId: (courseId,lessonId,callback) => {
       Course.findOne({_id: courseId},function(err, course) {
          if (err) {
            callback(err, null);
          } else {
            let lesson = course.lessons.find(l => l._id == lessonId);
            let comments = lesson.comments;
                comments.map((comment)=>{

                  UserController.findFullNameById(comment.user).then(name=>{
                      return {userId: comment.user,name: name,content: comment.content};
                  });

               });
              callback(null, comments);
            }
        });
 }
0 голосов
/ 09 февраля 2020

Как прокомментировал @SuleymanSah, я попытался использовать .populate, и это сработало хорошо. Я думаю, что это правильный подход по точным причинам, на которые он указал. Вот как я это сделал:

Lesson.findOne({ _id: lessonId }).
populate('comments.user').
exec(function(err, lesson) {
  if (err) {
    console.log(err);
    return callback(err, null);
  }
  if (!lesson) {
    console.log("No record found");
    return callback(err, null);
  }
  return callback(null, lesson.comments);
});
0 голосов
/ 18 января 2020

Начните с отбрасывания обратных вызовов и фактического использования обещаний для await. Вы не указали, что такое find, но есть вероятность, что это современная библиотека, поддерживающая обещания. Так что напишите

async function findAllCommentsByLessonId(courseId, lessonId) {
  const [course] = Course.find({_id: courseId};
  const lesson = course.lessons.find(l => l._id !== lessonId);
  const comments = lesson.comments.map(async c => {
    const name = await UserController.findFullNameById(c.user)
    return {
      userId: c.user,
      name,
      content: c.content
    };
  });
}

module.exports.findFullNameById = async (userId) => {
  const [user] = await User.find({_id: userId});
  return user.name + " " + (user.lname ? user.lname : "");
};

Тогда вы заметите, что comments - это не массив пользователей, а массив обещаний для пользователей, поэтому заключите его в вызов await Promise.all(…).

...