【问题标题】:Pass large amount of data through res.render (Node)通过 res.render (Node) 传递大量数据
【发布时间】:2022-01-26 02:31:15
【问题描述】:

试图通过 .render 函数传递一个包含多达 3000 个名称的对象。

检查了所有内容并得出结论,它不是数据库,也不是页面,我认为它是数据“复制”到响应。我看到有人提出了一些关于 AJAX 的建议并更改了响应,一次 10 个名称,但恐怕我不完全确定如何执行它.. 代码不在我的机器上,所以会尽力描述它:

在 route.js 中

import addRequestPageController from "../controllers/addRequestPageController"

app.get('/add_request', ... , addRequestPageController.addRequest)

在 addRequestPageController.js 中

import DBConnection from "../configs/connectDB" // This is where the mysql DB connection is configured

let addRequest = function(req, res) {
var obj = {}
try {

 DBConnection.query(..(a query brings 50~ names).., function(err, rows) {
     if (err) {
        res.render("error.ejs")
     } else { // No errors
         obj.docNames = rows
         // Each doctor has firstName and lastName attributes
         res.render("addRequest.ejs", obj)
     }
 })

 DBConnection.query(..(query-3000 rows with drug names, ratings).., function(err, rows) {
     if (err) {
        res.render("error.ejs")
     } else { // No errors
         obj.drugNames = rows
         // Each drug has it's name(varchar) and rating (float value)
         res.render("addRequest.ejs", obj)
     }
 })

} catch{...}

}

module.exports = {
addRequest: addRequest
}

添加 addRequest.ejs 以供进一步参考-

在 addRequest.ejs 中

...


<select name="docNames" id="docNames">
      <option value="">--Please choose an option--</option>
      <% docNames.forEach(function(doc) { %>
      <!-- Start of forEach -->
      <option value="<% doc.firstName + " " + doc.lastName %>">
      <!-- that was to put a value of the doctor's name -->
      <% doc.firstName + " " + doc.lastName %>
      <!-- and that was to put the actual value the user sees -->
      </option>
      <!-- End of forEach -->
      <% }) %> 
</select>

<select name="drugNames" id="drugNames">
     <option value="">--Please choose an option--</option>
     <% drugNames.forEach(function(drug) { %> 
     <!-- Start of forEach -->
     <option value="<% drug.drug_name %>">
     <!-- that was to put a value of the drug's name -->
     <% drug.drug_name + " and rating of : " + drug.rating %>
     <!-- that was to put the actual value the user sees -->
     </option>
     <!-- End of forEach -->
     <% }) %> 
</select>

...

所以基本上我将参数传递给页面,但它卡在加载并且没有给我任何错误。 有没有办法只更改 addRequest 以获得所需的结果?

edit:添加了addRequest.ejs,并编辑了addRequestPageController.js。 但是,我确实尝试渲染一个没有任何内容的页面,但它仍然无法加载.. 感觉坏人

【问题讨论】:

  • 为什么要传递大量数据来渲染?这不是最佳做法
  • 您能说明addReqest.ejs 对所有这些数据做了什么吗?
  • 3000 个名字与即使是基本图像相比也算不上太多数据。如果名称的平均长度为 30 个字节,那么您的数据仍然少于 90k。发送应该没有问题。你遇到了什么确切的问题?卡在加载可能是由其他原因引起的。作为参考,CNN主页超过1MB。
  • 刚刚编辑了@Bergi 帖子,尽管正如我在下面提到的,我尝试在不使用“docNames”或“drugNames”的情况下呈现不同的页面,但无济于事):非常感谢你们..
  • @jfriend00 我真的希望这是我在 ejs 做过的事情,所以你的消息给了我希望

标签: javascript node.js


【解决方案1】:

您调用res.render() 两次,这是一个先完成的竞争条件。而且,第一个完成的将只有一个数据,而不是两个。第一次调用res.render() 可能会失败,因为您的模板引用了两组数据,但第一次调用res.render() 将只有obj 中设置的两个属性之一。 Express 将忽略对res.render() 的第二次调用,因为您只能调用一次。您应该会在日志中的某处看到错误。

您需要先收集模板的所有数据,以便在将所需的所有数据传递给res.render() 之前调用它。这是一种方法:

import DBConnection from "../configs/connectDB" // This is where the mysql DB connection is configured

export function addRequest(req, res) {
    DBConnection.query(..(a query brings 50~names).., function(err, rows) {
        if (err) {
            console.log(err);
            res.render("error.ejs");
        } else { // No errors
            const obj = { docNames: rows };
            // Each doctor has firstName and lastName attributes
            DBConnection.query(..(query - 3000 rows with drug names, ratings).., function(err, rows) {
                if (err) {
                    console.log(err);
                    res.render("error.ejs");
                } else { // No errors
                    obj.drugNames = rows
                    // Each drug has it's name(varchar) and rating (float value)
                    res.render("addRequest.ejs", obj)
                }
            });
        }
    });
}

另外,我很困惑为什么您使用import 加载数据库模块,然后使用module.exports。这两个不在一起。选择一个模块模块或另一个,而不是两者的混合。 import 将与 export 一起使用,require() 将与module.exports 一起使用。这也需要修复,如果您尝试使用带有importexport 的ESM 模块,则需要使用.mjs 文件扩展名或在package.json 中使用type: "module" 正确指定nodejs。


请注意,我总是记录一个导致请求返回错误的错误。如果发生此类错误并且客户端报告错误页面,您需要知道的第一件事是为什么会发生该错误,以便在服务器日志中获取该信息。

而且,如果您对数据库使用 promise 接口而不是普通的回调接口,您可以使用 Promise.all() 并行运行这两个查询,并且可能比这种串行执行请求的机制更快地产生结果。虽然可以在没有 Promise 的情况下对这些请求进行并行编程,但要正确处理(并通过适当的错误处理)是一件很痛苦的事情,并且 Promise 是语言中支持这样做的机制,它们使它变得容易得多。

【讨论】:

  • 另外值得一提的是,importexport 仅允许使用 mjs 文件扩展名或在 package.json 中指定:type: "module";否则为require()exports/module.exports
  • "第二次没有docNames 数据。" - 实际上不,第二次调用将有两个查询结果,因为它是相同的obj。但是当然第二次写 http 响应会失败。 OP 真的应该在他们的服务器日志中出现错误。
  • @Bergi - 实际上,这是一个竞争条件,因为两个 Db 调用都是并行运行的。谁知道哪一个会先完成。第一个完成的将只有obj 中的一条数据,并将调用res.render()。对res.render() 的第二次调用将被忽略。我已经编辑了我的答案以详细说明这种状态。无论哪种方式,他们都必须先获取所有数据,然后使用所有数据调用一次res.render()
  • 是的,我的意思是第二次调用回调/第二次调用res.render 不是源顺序中的第二次:-)
猜你喜欢
  • 2018-07-29
  • 1970-01-01
  • 1970-01-01
  • 2012-04-29
  • 2015-12-24
  • 1970-01-01
  • 2018-03-06
  • 2018-05-04
  • 1970-01-01
相关资源
最近更新 更多