使用async/await实现查询等待时渲染页面的问题排查
ERR_HTTP_HEADERS_SENT错误解析及加载状态实现方案
错误根源
你这段代码的问题很明确:一个HTTP请求只能对应一次响应。你先调用await res.render('waiting.ejs'),这已经把完整的响应(包括响应头和页面内容)发给客户端了,之后又调用res.render('index.ejs'),试图再次发送响应,这就违反了HTTP协议规则,直接触发了Error [ERR_HTTP_HEADERS_SENT]错误。
正确实现思路
要实现“先显示加载动画,查询完成后展示结果页”的效果,不能靠后端两次渲染,得让前端和后端配合:
- 后端先返回包含加载动画的页面;
- 前端页面加载完成后,自动发起AJAX请求去查询数据库;
- 后端处理查询请求,返回数据;
- 前端拿到数据后,要么跳转到结果页,要么直接在当前页面替换内容。
代码示例
后端代码拆分
把原来的接口拆成两个:一个返回加载页面,一个处理数据查询:
// 返回带加载动画的页面 board: (req, res) => { res.render('waiting.ejs'); }, // 异步处理数据库查询并返回JSON数据 boardData: async (req, res) => { try { const result = await new Promise((resolve, reject) => { db2.query(queryboard.join(';'), (err, result) => { if (err) { console.log(`sql error ${queryboard}`); reject(err); } resolve(result); }); }); res.json({ success: true, data: result }); } catch (err) { res.status(500).json({ success: false, error: '数据库查询失败' }); } }
前端waiting.ejs页面
在页面里放加载GIF,然后用JS发起请求:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>数据加载中</title> <style> .loading-container { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); text-align: center; } .loading-gif { width: 60px; height: 60px; } </style> </head> <body> <div class="loading-container"> <img class="loading-gif" src="/images/loading.gif" alt="加载中"> <p>正在查询数据,请稍候...</p> </div> <script> // 页面加载完成后自动请求数据 async function fetchData() { try { const response = await fetch('/boardData'); const result = await response.json(); if (result.success) { // 方式1:跳转到结果页,可通过URL参数传递数据 window.location.href = `/boardResult?data=${encodeURIComponent(JSON.stringify(result.data))}`; // 方式2:直接在当前页面渲染结果(推荐,无跳转更流畅) // const pageResponse = await fetch('/boardResult', { // method: 'POST', // headers: { 'Content-Type': 'application/json' }, // body: JSON.stringify(result.data) // }); // document.body.innerHTML = await pageResponse.text(); } else { alert(`查询失败:${result.error}`); } } catch (err) { alert('网络请求失败,请刷新重试'); } } window.onload = fetchData; </script> </body> </html>
额外说明
- 如果选择跳转方式,需要再写一个
boardResult接口来接收数据并渲染index.ejs; - 也可以用WebSocket实现实时推送,但AJAX是最轻量化的方案,适合你的场景;
- 记得处理异常情况,比如数据库查询失败、网络超时等,提升用户体验。
内容的提问来源于stack exchange,提问作者fosfik
相关产品推荐
相关产品推荐

