如何在for循环中运行mongoose查询并使res.render等待

时间:2018-04-30 23:01:05

标签: node.js mongoose

首先,如果标题是荒谬的,我道歉。我只是很难解释我遇到的问题。

我正在尝试借助其他集合中的数据从集合中检索数据。通常情况下,在另一个查询中运行查询工作正常,但在混合中引入for循环使我难以修复。

所以,这就是我想要的 - 我在一个名为'all_collections'的数组中有一组对象。每个集合都包含另一个名为“资源”的数组。我的目标是在每个对象的索引0处检索'_id'。

这就是我的尝试 -

    router.get('/profile', mid.requiresLogin, function(req, res, next) {
        var output_collections = '';
        User.findOne({ _id: req.session.userId }, function(err, user) {
            for(var i=0; i<user.all_collections.length;i++) {
                Resource.findOne({_id:user.all_collections[i].resources[0]}, function(err, resource) {
                    output_collections += '<div>'+resource.image+'</div>';
                })
            }

        res.render('profile',{collections:output_collections});
     });
  });

我也试过了 -

    var output_collections = [];
       User.findOne({ _id: req.session.userId }).then(function(user) {
          output_collections.push(user);
          for (var i = 0; i < user.all_collections.length; i++) {
               Resource.findOne({ _id: user.all_collections[i].resources[0] })
            .exec(function(error, resource) {
                output_collections.push('div>'+resource.image+'</div')
            });
    }
    console.log('1');
    return Promise.all(output_collections);
       }).then(function(output_collections) {
            console.log(output_collections);
            res.render('profile', {
               title: 'Profile',
               name: output_collections[0].name,
               email: output_collections[0].email,
               collections: output_collections
             })
     }).catch(function(error) {
          next(error);
     });

'output_collections'变量在for循环之外变为空。我很确定这是创建问题的for循环。如果有人能够正确地告诉我如何正确地做到这一点(如果这里的使用是完全错误的话),我将非常感激。

2 个答案:

答案 0 :(得分:0)

router.get('/profile', mid.requiresLogin, async (req, res, next) => {
    let output_collections = []
    let user = await  User.findOne({ _id: req.session.userId })

    for(let i=0; i<user.all_collections.length;i++) {
         let rerource = await Resource.findOne({_id:user.all_collections[i].resources[0]})
         output_collections.push('<div>'+ resource.image+'</div>')

    }
    res.render('profile',{collections:output_collections})
})

答案 1 :(得分:0)

  

&#39; output_collections&#39;变量在for循环之外变为空。

这是因为Resource.findOne()是一个异步调用,当它完成从db中获取数据时,res.render()就已经完成了。

  

我相当肯定它是创造问题的for循环。如果有人能告诉我如何正确地做到这一点

是。你是对的。 for循环异步任务,但期望以同步方式生成。您可以通过在Promise

中包装Resource.findOne()来更改此设置

对代码进行更改

'use strict';

let _ = require('lodash');

getUserDetailById(req.session.userId).then(user => {
  return Promise.all([
    user,
    getResourceDetailsForUser(user.all_collections)
  ]);
}).then(results => {
  let [{name, email}, collections] = results;
  res.render('profile', {
    title: 'Profile',
    name: name,
    email: email,
    collections: collections
  });
}).catch(err => {
  console.log('Error occured when fetching resource', err);s
});

function getResourceDetailsForUser(collections) {
  if (_.isEmpty(collections)) {
    return [];
  }

  return _.map(collections, collection => {
    return Resource.findOne({
      _id: collection.resources[0]
    }).then((error, resource) => {
      return `<div>${resource.image}</div>`;
    });
  });
}

function getUserDetailById(userId) {
  return User.findOne({_id: userId});
}