如何等待内部带有mongodb查询的嵌套forEach语句返回函数

时间:2019-06-29 05:19:18

标签: arrays node.js mongodb foreach

我很难弄清楚嵌套forEach()函数与node.js的异步行为。我不确定应该在哪里创建并返回承诺等等。

我尝试将getFeed()函数的所有逻辑包装到return new Promise()中,但是我认为在嵌套forEach()完成之前要调用resolve。

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将等待嵌套forEach逻辑完成,然后console.log结果。

3 个答案:

答案 0 :(得分:0)

从文档中

  

forEach()对每个数组元素执行一次回调函数;与map()或reduce()不同,它始终返回值 undefined

这意味着您不能等待它,因为您永远都无法从中得到回报。

您应该使用forwhile循环或bluebird之类的库来遍历数组并返回Promise。

答案 1 :(得分:0)

您可以使用一个promise数组来等待它们。

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 });
    })

答案 2 :(得分:-1)

我认为这可以帮助您获得所需的输出。

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 });