Node.js中通过render向EJS传递两个查询结果遇阻求助
解决EJS模板同时接收两个查询结果的问题
我来帮你搞定这个问题!看你的代码,现在的问题主要有两个:一是当前的接口都是直接返回JSON数据,没有把结果传给EJS模板;二是两个异步查询没有同步处理,没法同时把两个列表数据一起渲染到页面上。另外还有个小问题,connection.end()放在了异步回调外面,会在数据库查询完成前就关闭连接,大概率会导致查询失败。
下面一步步给你修正:
第一步:把DAO的查询方法改成返回Promise(更易处理异步)
如果你的DAO目前是用回调的方式,建议改成Promise,这样后续用async/await处理多个异步查询会更清晰:
// 修改UfesDAO的lista方法 class UfesDAO { constructor(connection) { this.connection = connection; } lista() { return new Promise((resolve, reject) => { this.connection.query('SELECT * FROM ufes', (err, results) => { if (err) return reject(err); resolve(results); }); }); } } // 同理修改CidadesDAO的lista方法 class CidadesDAO { constructor(connection) { this.connection = connection; } lista() { return new Promise((resolve, reject) => { this.connection.query('SELECT * FROM cidades', (err, results) => { if (err) return reject(err); resolve(results); }); }); } }
第二步:创建统一的路由处理函数,同时获取两个列表并渲染EJS
写一个专门的路由函数,用Promise.all并行获取UF和城市列表,拿到结果后一起传给EJS模板:
// 处理表单渲染的路由函数 const renderFormPage = async (req, res) => { try { // 获取数据库连接 const connection = app.infra.connectionFactory(); const ufesDAO = new app.infra.UfesDAO(connection); const cidadesDAO = new app.infra.CidadesDAO(connection); // 并行执行两个查询,等待所有结果返回 const [ufList, cityList] = await Promise.all([ ufesDAO.lista(), cidadesDAO.lista() ]); // 查询完成后再关闭连接 connection.end(); // 把两个列表数据传给EJS模板(假设你的模板文件叫form.ejs) res.render('form', { ufOptions: ufList, cityOptions: cityList }); } catch (error) { console.error('加载数据出错:', error); res.status(500).send('服务器加载数据失败,请稍后重试'); } }; // 绑定路由,比如访问/form时渲染页面 app.get('/form', renderFormPage);
第三步:在EJS模板里渲染下拉框
现在在你的EJS模板里,就可以用传过来的ufOptions和cityOptions生成下拉选项了:
<!-- form.ejs中的下拉框部分 --> <div class="form-group"> <label for="uf-select">选择UF:</label> <select id="uf-select" name="uf" class="form-control"> <% ufOptions.forEach(uf => { %> <option value="<%= uf.id %>"><%= uf.nome %></option> <% }) %> </select> </div> <div class="form-group"> <label for="city-select">选择城市:</label> <select id="city-select" name="cidade" class="form-control"> <% cityOptions.forEach(city => { %> <option value="<%= city.id %>"><%= city.nome %></option> <% }) %> </select> </div>
关键要点说明
- 异步处理:用
Promise.all可以让两个数据库查询并行执行,比嵌套回调更高效也更易读;async/await让异步代码看起来像同步代码,降低出错概率。 - 连接关闭时机:一定要在所有异步查询完成后再调用
connection.end(),否则会导致数据库连接提前关闭,查询失败。 - 模板传值:用
res.render()替代res.json(),才能把数据传给EJS模板进行渲染,而不是直接返回JSON接口。
内容的提问来源于stack exchange,提问作者Rodrigo Martins
相关产品推荐
相关产品推荐

