Express.js插入数据库后刷新页面出现ERR_HTTP_HEADERS_SENT错误怎么解决?
问题原因及解决方法
报错原因
Cannot set headers after they are sent to the client错误的触发逻辑是HTTP协议规定单次请求只能向客户端返回一次响应,你代码中存在三个导致问题的点:
- 最终处理函数
showToken中先后调用了res.json()和res.redirect()两个方法,前者已经将响应头和响应体完整发送给客户端,后者尝试再次修改响应头返回跳转响应,直接触发报错。 - 中间件
importToken中的数据库插入方法Token.insertMany是异步操作,你没有添加await等待执行完成,会出现还没等插入操作结束就已经调用next()走到后续逻辑,若插入操作后续抛出错误触发catch中的返回响应逻辑,也会出现二次返回响应的问题。 - 你前端是通过axios发起异步POST请求,后端直接返回redirect指令不会触发浏览器页面跳转,axios默认不会处理301跳转逻辑,必须前端手动控制跳转。
修复步骤
- 修复
importToken中间件,添加await等待数据库操作完成
exports.importToken = async (req, res, next) => { try { await Token.insertMany(JSON.parse(req.body.XLSXdata)); next(); } catch (err) { return res.status(400).json({ status: 'fail', message: '写入token到数据库时发生错误', }); } };
- 修复
showToken函数,删除冗余的redirect方法,仅返回JSON响应
exports.showToken = async (req, res) => { const newTokensList = JSON.parse(req.body.XLSXdata); res.json({ status: 'success', data: newTokensList, }); };
- 修复前端axios请求逻辑,收到成功响应后手动执行页面跳转,同时修正原有catch逻辑的错误
if (submitXLSX) { submitXLSX.addEventListener('click', async (event)=>{ event.preventDefault(); try { const XLSXdata = await readXLSXtoJSON(selectedFile); if (XLSXdata) { axios.post('http://localhost:3000/api/1.0/tokens', { XLSXdata }).then(res => { if(res.data.status === 'success') { // 手动跳转到目标页面,完成刷新逻辑 window.location.href = '/admin/tokens'; } }).catch(err => { console.log('请求出错:', err); }) } } catch (err) { console.log('读取文件出错:', err); } }) }
内容的提问来源于stack exchange,提问作者Matyas
相关产品推荐
相关产品推荐

