Express+Mongoose获取数据后无法存入列表的问题求助
问题:Express + Mongoose 无法将MongoDB数据存入列表传递给EJS模板
使用Express.js和Mongoose从MongoDB集合获取数据存入列表,再传递给EJS模板,但最终列表始终为空。以下是相关信息:
路由代码
app.get("/", (req, res) => { let item = []; General.find(null, (err, data)=>{ if(err){ console.log(err); } else { data.forEach(element => { item.push(element.name); }); console.log("pushed "+item); } }); console.log("final "+item); res.render("index", { title: "Welcome", list: item}); });
控制台输出
listening 3000 final pushed item-1,item-2
数据库集合数据
[ { _id: ObjectId("63d165717d847e937728e63b"), name: 'item-1', __v: 0 }, { _id: ObjectId("63d165857d847e937728e63e"), name: 'item-2', __v: 0 } ]
项目配置信息
const express = require("express"); const bodyParser = require("body-parser"); const mongoose = require("mongoose"); mongoose.set("strictQuery", false); mongoose.connect("mongodb://127.0.0.1:27017/todolistDB", { useNewUrlParser: true }); const genSchema = new mongoose.Schema({ name : String }); const General = mongoose.model("General", genSchema); const app = express(); app.set('view engine', 'ejs'); app.use(bodyParser.urlencoded({ extended: "true" })); app.use(express.static("public"));
问题原因与解决办法
问题核心
Mongoose的find方法是异步操作,不会阻塞后续代码执行。你的代码中,console.log("final " + item)和res.render在find的回调函数执行前就已经运行,此时item还未被填充数据,所以是空数组。控制台输出顺序(先打印final,再打印pushed)也验证了这一点——异步回调在主流程代码执行完后才触发。
解决方式1:将渲染逻辑移到回调内部
把res.render放在find的回调函数里,确保数据获取并处理完成后再渲染模板:
app.get("/", (req, res) => { let item = []; General.find(null, (err, data)=>{ if(err){ console.log(err); res.status(500).send("获取数据失败"); } else { data.forEach(element => { item.push(element.name); }); console.log("pushed "+item); console.log("final "+item); // 数据就绪后再渲染模板 res.render("index", { title: "Welcome", list: item}); } }); });
解决方式2:使用async/await(推荐)
利用async/await语法让异步代码更易读,逻辑更清晰:
app.get("/", async (req, res) => { try { let item = []; // 等待find操作完成,拿到数据 const data = await General.find(null); data.forEach(element => { item.push(element.name); }); console.log("pushed "+item); console.log("final "+item); res.render("index", { title: "Welcome", list: item}); } catch (err) { console.log(err); res.status(500).send("获取数据失败"); } });
两种方式都能保证在数据处理完成后,再将列表传递给EJS模板,模板就能拿到正确的非空数据了。
内容的提问来源于stack exchange,提问作者Shubham Verma
相关产品推荐
相关产品推荐

