You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Mongoose查询外部变量无法访问,需多查询后统一渲染EJS

问题

我尝试使用Mongoose查询所有用户,并将结果传入res.render()以在EJS文件中展示。

以下是我的代码:

const customersView = (req, res) => {

    const emailsArr = [];

    User.find({}, function(err, users) {
        users.forEach(function(user) {
            emailsArr.push(user.email);
        });

        console.log('Inside: ' + emailsArr);
        // I can put res.render() here
    });

    console.log('Outside: ' + emailsArr);

    // But I have to do some more queries here and then send them back all at once

    res.render('customers.ejs', {users: emailsArr});
}

但在User.find()外部,emailsArr为空。

控制台输出如下:

[nodemon] restarting due to changes...
[nodemon] starting `node index.js`
Server started
Connected to MongoDB
Outside: 
Inside: test@test,admin@admin

我可以在find()内部调用res.render(),但问题是我需要在该用户查询之后执行更多查询,再将所有结果一次性传递给EJS。请问该如何解决?

解决方案

这是因为Mongoose的查询是异步操作,代码会先执行User.find()外部的console.log和res.render,此时查询还没完成,所以emailsArr是空的。要解决多查询后统一渲染的问题,有几种常用方法:

方法1:Promise链式调用(适合少量后续查询)

Mongoose的查询方法默认返回Promise,可通过.then()链式处理多个查询:

const customersView = (req, res) => {
    // 第一个查询:只获取用户email字段,提升效率
    User.find({}, 'email')
        .then(users => {
            const emailsArr = users.map(user => user.email);
            // 示例:执行第二个查询,比如获取订单数据
            return Order.find({}).then(orders => ({ emailsArr, orders }));
        })
        .then(({ emailsArr, orders }) => {
            // 所有查询完成后统一渲染
            res.render('customers.ejs', { users: emailsArr, orders });
        })
        .catch(err => {
            console.error(err);
            res.status(500).send('服务器错误');
        });
}

方法2:async/await(最清晰直观)

用async标记函数,await等待每个异步查询完成,逻辑和同步代码一致:

const customersView = async (req, res) => {
    try {
        // 等待用户查询完成
        const users = await User.find({}, 'email');
        const emailsArr = users.map(user => user.email);
        
        // 执行后续其他查询,比如获取客户统计数据
        const customerStats = await Stats.findOne({ type: 'customer' });
        // 可添加更多查询...
        
        // 所有数据就绪后渲染页面
        res.render('customers.ejs', { users: emailsArr, customerStats });
    } catch (err) {
        console.error(err);
        res.status(500).send('服务器错误');
    }
}

注意事项

  • 避免嵌套过多回调(回调地狱),优先使用async/await或Promise链式写法
  • 查询时指定需要返回的字段(如User.find({}, 'email')),减少数据传输量
  • 必须添加错误捕获逻辑,防止未处理的异常导致服务器崩溃

内容的提问来源于stack exchange,提问作者Phat Tran

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 01:40:44