Nodejs 如果需要同时render多个数据库查询结果,怎么写代码比较好?

Nodejs 如果需要同时render多个数据库查询结果,怎么写代码比较好?

app.render(‘email’, { a:a , b:b ,c:c ,d:d}, function(err, html){});

如果上面abcd都是数据库查询结果的话?那么要写代码,除了不断地查询嵌套,最后渲染,不知道还有什么比较好的代码结构吗? 谢谢了。

4 回复

在 Node.js 中,如果你需要同时从多个数据库查询中获取数据并将其传递给模板进行渲染,使用回调嵌套(即所谓的“回调地狱”)并不是最佳实践。更好的方法是利用 Promise 或 async/await 来管理异步操作,从而使代码更清晰、易于维护。

下面是一个使用 async/await 和 Promise 的示例,它展示了如何同时执行多个数据库查询,并将结果传递给模板进行渲染。

示例代码

假设我们正在使用 mongoose 作为 ORM 工具来与 MongoDB 进行交互。

const express = require('express');
const mongoose = require('mongoose');

const app = express();
mongoose.connect('mongodb://localhost:27017/mydatabase', { useNewUrlParser: true, useUnifiedTopology: true });

// 定义模型
const A = mongoose.model('A', new mongoose.Schema({ name: String }));
const B = mongoose.model('B', new mongoose.Schema({ name: String }));
const C = mongoose.model('C', new mongoose.Schema({ name: String }));
const D = mongoose.model('D', new mongoose.Schema({ name: String }));

// 异步函数,用于同时查询多个数据库
async function fetchData() {
    try {
        // 同时发起所有查询
        const [a, b, c, d] = await Promise.all([
            A.find().exec(),
            B.find().exec(),
            C.find().exec(),
            D.find().exec()
        ]);

        // 渲染模板
        app.render('email', { a, b, c, d }, (err, html) => {
            if (err) return console.error(err);
            console.log(html); // 或者可以将 html 发送到客户端
        });
    } catch (error) {
        console.error(error);
    }
}

// 模拟一个路由调用 fetchData 函数
app.get('/', async (req, res) => {
    await fetchData();
});

app.listen(3000, () => console.log('Server running on port 3000'));

解释

  1. 定义模型:首先定义与数据库表对应的 Mongoose 模型。
  2. fetchData 函数:这是一个异步函数,它使用 Promise.all 方法并发地执行多个数据库查询。
  3. 并发查询Promise.all 接受一个数组,其中包含多个 Promise 对象。当所有的 Promise 都成功解析后,它会返回一个包含所有解析值的数组。
  4. 渲染模板:一旦所有查询都完成,我们将查询结果传递给模板进行渲染。
  5. 错误处理:通过 try...catch 结构处理可能发生的任何错误。

这种方法避免了回调嵌套的问题,使代码更加清晰和易于理解。


数据库查询不可避免,嵌套可以用一些库来处理比如async

async.parallel({
a: //查询a的代码
b://查询b的代码
....
}, function(err, res) {});

在Node.js中,如果你需要同时渲染多个数据库查询结果,可以使用Promise或者async/await来处理异步操作,这样可以使代码更加清晰和易于维护。下面是一个使用async/await的例子,假设我们使用的是MongoDB和Mongoose:

示例代码

首先定义一个简单的Mongoose模型:

const mongoose = require('mongoose');

const UserSchema = new mongoose.Schema({
    name: String,
});

const PostSchema = new mongoose.Schema({
    title: String,
    authorId: {
        type: mongoose.Schema.Types.ObjectId,
        ref: 'User'
    }
});

const User = mongoose.model('User', UserSchema);
const Post = mongoose.model('Post', PostSchema);

module.exports = { User, Post };

然后,在你的路由处理函数中,你可以这样写:

const express = require('express');
const router = express.Router();
const { User, Post } = require('./models'); // 假设这是你的模型路径

router.get('/multiple-queries', async (req, res) => {
    try {
        const [users, posts] = await Promise.all([
            User.find({}), // 查询所有用户
            Post.find({}).populate('authorId') // 查询所有文章,并且把作者ID填充为具体的用户信息
        ]);

        res.render('email', { users, posts });
    } catch (err) {
        console.error(err);
        res.status(500).send('Server Error');
    }
});

module.exports = router;

解释

  1. 使用Promise.all():这个方法接收一个包含多个Promise的数组,当所有的Promise都成功完成时,它返回一个包含每个Promise结果的新数组。这样可以确保所有查询都执行完毕后再进行下一步。

  2. async/await:使异步代码看起来像同步代码一样,提高了可读性和可维护性。

  3. 错误处理:通过try...catch语句捕获并处理可能发生的错误,避免程序崩溃。

  4. 渲染视图:一旦所有查询完成,我们将查询结果作为参数传递给模板引擎(如EJS、Pug等)以渲染最终页面。

这种方法避免了深层次的回调嵌套(callback hell),使得代码更加简洁和易于理解。

回到顶部