Как ждать вложенных операторов forEach с запросами mongodb внутри для возврата функции - PullRequest
1 голос
/ 29 июня 2019

Мне трудно разобраться в асинхронном поведении вложенных forEach() функций с помощью node.js. Я не уверен, где мне следует создать и вернуть обещание и т. Д.

Я попытался обернуть всю логику функции getFeed() в return new Promise(), но я думаю, что решение вызывается до того, как вложенные forEach() будут выполнены.

friends = user_info.friends;

function GetFeed() {
    let post_ids = [];
    try {
        friends.forEach(async function(friend_id) {
        const posts = await db.collection('users').findOne(
              { _id: ObjectId(friend_id) },
              { projection: { posts: 1 }}
        );
        posts.posts.forEach(function(post_id) {
              console.log(post_id);
              post_ids.push(post_id);
           });
        });
        return new Promise((resolve, reject) => {
            resolve(post_ids);
        });
    } catch (err) {
         return res.status(500).json({ error: 'Internal server error, unable to collection post ids from the database.' });
    }
}

GetFeed()
  .then((post_ids) => {
        console.log(post_ids);
        return res.status(200).json({ post_ids: post_ids });
   })

операторы console.log () показывают, что GetFeed().then() выполняется перед оператором console.log() во внутреннем цикле forEach. Я ожидаю, что GetFeed().then() console.log будет ожидать завершения работы логики nest forEach, а затем console.log с результатом.

Ответы [ 3 ]

0 голосов
/ 29 июня 2019

Из документов:

forEach () выполняет функцию обратного вызова один раз для каждого элемента массива;в отличие от map () или redu (), он всегда возвращает значение undefined .

Это означает, что вы не можете ждать его, так как вы никогда не получите обещание вернуться из него.

Вы должны использовать цикл for или while или библиотеку наподобие bluebird для перебора массива и возврата обещаний.

0 голосов
/ 29 июня 2019

Вы можете использовать массив обещаний, ожидающих их.

friends = user_info.friends;

async function GetFeed() {
    let post_ids = [];


    let postsPromiseArray = await Promise.all(
        friends.map(friend_id => {
            return db.collection('users').findOne(
                { _id: ObjectId(friend_id) },
                { projection: { posts: 1 } }
            );
        })
    )

    postsPromiseArray.forEach(posts => {
        posts.posts.forEach(function (post_id) {
            post_ids.push(post_id);
        });
    })

    return post_ids;
}

GetFeed()
    .then((post_ids) => {
        console.log(post_ids);
        return res.status(200).json({ post_ids: post_ids });
    })
0 голосов
/ 29 июня 2019

Я думаю, что это может помочь вам получить желаемый результат.

friends = user_info.friends;

    async function GetFeed() {
        let post_ids = [];
        try {
           await friends.forEach(async function(friend_id) {
                const posts = await db.collection('users').findOne(
                    { _id: ObjectId(friend_id) },
                    { projection: { posts: 1 }}
                );
                posts.posts.forEach(function(post_id) {
                    console.log(post_id);
                    post_ids.push(post_id);
                });
            });
            return post_ids;
        } catch (err) {
            return res.status(500).json({ error: 'Internal server error, unable to collection post ids from the database.' });
        }
    }

    var post_ids = GetFeed()
    console.log(post_ids);
    return res.status(200).json({ post_ids });
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...