Выполнение запроса продолжения внутри цикла forEach. Не может обработать результат - PullRequest
0 голосов
/ 20 мая 2019

Я выполняю этот запрос секвелизации, который возвращает некоторые сообщения на форуме.И для каждого из результатов я запускаю второй запрос, который возвращает мне категории / теги каждого сообщения на форуме.Теперь цикл forEach заканчивается перед выполнением всех запросов, потому что он асинхронный, я знаю эту часть.Как мне справиться с этим правильно и делать то, что я пытаюсь сделать?Я хочу прикрепить массив тегов / категорий к каждому сообщению и отправить массив сообщений в представление ejs и вызвать next ();

Я пробовал обещание обещания в виде обещания. Все (и асинхронно-ожидание).Но я хочу, чтобы категории были прикреплены к каждому объекту публикации.

Forum.findAll({
    attributes: ["f_post_id", "f_post_title", "like_count", "createdAt"],
    limit: limitPost.FORUM,
    subQuery: false,
    raw: true,
    group: ['forum.f_post_title'],

    include: [{
        attributes: ["user_name"],
        model: User,
        required: true, // returns everything in a clean single object format
                        // setting it to false, results in nested arrays
    }, {
        attributes: [[Sequelize.fn("COUNT", Sequelize.col("forum_answers.answer_id")), "ansCount"]],
        model: ForumAnswer,
        required: true,
    }]
})
    .then(fetchedPost => {

        fetchedPost.forEach(post => {

            ForumTag.findAll({
                attributes: [],
                raw: true,

                where: {
                    f_post_id: post.f_post_id,
                },
                include: [{
                    attributes: ["tag_name"],
                    model: Tag,
                    required: true,
                }]
            })
                .then(postTags => {

                    post.tags = postTags.map(postTag => postTag["tag.tag_name"]);

                })
                .catch(err => console.log(err));

        });

        res.locals.fetchedPost = fetchedPost;
        next();

    })
    .catch(err => console.log(err));

Это ожидаемый результат ниже:

{ 
  f_post_id: 1,
  f_post_title: 'learn js',
  like_count: 12,
  createdAt: 2019-05-19T00:00:00.000Z,
  'user.user_name': 'mrscx',
  'forum_answers.ansCount': 3,
  tags: [ 'JavaScript', 'Database' ] 
}

Но теги не прикрепляются из-за forEachокончание цикла.

Как это исправить?

Ответы [ 2 ]

0 голосов
/ 20 мая 2019

Судя по всему, проблема может заключаться в том, как вы обрабатываете обещания.Вы на самом деле не ожидаете обработки обещаний в цикле forEach, а вместо этого возвращаете результат до этого.Один из способов исправить это - что-то вроде:

Forum.findAll({
    attributes: ["f_post_id", "f_post_title", "like_count", "createdAt"],
    limit: limitPost.FORUM,
    subQuery: false,
    raw: true,
    group: ['forum.f_post_title'],

    include: [{
        attributes: ["user_name"],
        model: User,
        required: true, // returns everything in a clean single object format
                        // setting it to false, results in nested arrays
    }, {
        attributes: [[Sequelize.fn("COUNT", Sequelize.col("forum_answers.answer_id")), "ansCount"]],
        model: ForumAnswer,
        required: true,
    }]
})
    .then(fetchedPost => {

        return Promise.all(fetchedPost.map(post => 
            ForumTag.findAll({
                attributes: [],
                raw: true,

                where: {
                    f_post_id: post.f_post_id,
                },
                include: [{
                    attributes: ["tag_name"],
                    model: Tag,
                    required: true,
                }]
            })
                .then(postTags => {

                    post.tags = postTags.map(postTag => postTag["tag.tag_name"]);
                    return post.save();
                })
                .catch(err => console.log(err));

        }).then(() => {
          res.locals.fetchedPost = fetchedPost;
          next();
      });
    })

Я уверен, что есть и более элегантные способы делать подобные вещи.Но это наименьшее количество изменений в исходном коде.

0 голосов
/ 20 мая 2019

Вызов findAll() является асинхронным, поэтому forEach вызывает ForumTag.findAll() для каждого сообщения, но возвращается сразу, прежде чем изменения вступят в силу. Кроме того, вам нужно вызвать метод save() в модели после модификации, чтобы сделать этот постоянный (например, post.save() после post.tags = ...)

Вы можете попробовать что-то вроде этого:

let promises = [];

fetchedPost.forEach(post => {

  ForumTag.findAll({
    attributes: [],
    raw: true,

    where: {
      f_post_id: post.f_post_id,
    },
    include: [{
      attributes: ["tag_name"],
      model: Tag,
      required: true,
    }]
  })
    .then(postTags => {

       post.tags = postTags.map(postTag => postTag["tag.tag_name"]);
       promises.push(post.save());

  })
    .catch(err => console.log(err));

});

Promise.all(promises).then(() => {
  res.locals.fetchedPost = fetchedPost;
  next();
}).catch(err => {
  throw err;
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...