Проблемы с добавлением элементов в массив в обещании - PullRequest
0 голосов
/ 28 марта 2020

Я создаю социальный медиа-сайт, где пользователи могут следить друг за другом. На одном из моих маршрутов я хочу провести l oop через текущий массив следующих пользователей, который является массивом идентификаторов, найти сообщения этих пользователей и добавить их в один большой массив, а затем отсортировать сообщения по дате. Проблема в том, что массив отправляется клиенту до того, как в него добавляются записи. Не уверен, если мне нужна какая-то функция asyn c или что.

мой маршрут для получения сообщений

const express = require('express')
const user = require("../models/user')
const router = express.Router()

router.get("/api/:username/following/posts", (req, res) => {
    let following = [...req.user.following, req.user._id]
    let posts = [], i;
    for(i = 0; i < following.length; i++){
        User.findById(following[i]).populate("posts")
            .then(user => {
                for(let b = 0; b < user.posts.length; b++){
                    posts.push(user.posts[b])
                }
            })
            .catch(err => {
                console.log(err)
            })
    }
    console.log(posts) // returns []
    res.json(posts) 
})

Ответы [ 2 ]

1 голос
/ 28 марта 2020

Использование async / await

router.get("/api/:username/following/posts", async (req, res) => {
    const following = [...req.user.following, req.user._id]
    const posts = [];
    for(let f of following){
        const user = await User.findById(f).populate("posts");
        posts.push(...user.posts);
    }
    console.log(posts)
    res.json(posts) 
})

с использованием только Promises

router.get("/api/:username/following/posts", (req, res) => {
    const following = [...req.user.following, req.user._id];
    Promise.all(following.map(f => User.findBy(f).populate("posts")))
    .then(users => {
        const posts = users.map(({posts}) => posts).flat();
        console.log(posts);
        res.json(posts);
    });
})

Основное отличие состоит в том, что код Promises только будет вызывать User.findBy параллельно, тогда как async / await будет вызывать их по очереди (не волнуйтесь, порядок поддерживается и в обещанной версии)

Если есть проблема с параллельным вызовом findBy и вы все еще не хотите использовать async / подождите, вы можете сделать это как:

router.get("/api/:username/following/posts", (req, res) => {
    const following = [...req.user.following, req.user._id];
    Promise.all(following.reduce((p, f) => p.then(results => User.findBy(f).populate("posts").then(user => [...results, user])), Promise.resolve([])))
    .then(users => {
        const posts = users.map(({posts}) => posts).flat();
        console.log(posts);
        res.json(posts);
    });
})
0 голосов
/ 28 марта 2020

Вы можете использовать async / await или просто переместить ваш res. json вызов в .then

...