使用fetch请求接口时res.redirect未触发页面跳转反而作为fetch响应加载如何解决?
问题根源
核心原因是 fetch 属于异步AJAX请求,和浏览器地址栏访问、form表单提交这类触发整页跳转的请求行为完全不同:
- 后端返回302重定向时,fetch默认会自动跟随重定向地址请求新资源,但所有响应内容只会返回给fetch的回调逻辑,绝对不会主动触发浏览器顶层页面的刷新或跳转,因此你看不到页面重载,flash消息也因为当前页面没有重新渲染而无法展示。
- 你提到的「重定向前手动结束fetch请求」完全不解决问题,该问题和fetch生命周期没有关系,是请求类型的固有特性。
另外补充个非直接相关的规范问题:点赞属于数据修改类操作,使用GET请求不符合REST API设计规范,后续优化建议改成POST请求。
解决方案
有两种常见的修复方案,可根据你的业务需求选择:
方案1:保留AJAX请求逻辑(更推荐,体验更流畅)
前后端配合调整逻辑,不再依赖后端重定向刷新页面:
- 后端修改返回逻辑,不返回重定向,直接返回JSON格式的操作结果:
router.get('/like/:post_id/', authController.isLoggedIn, async (req, res, next) => { try { // 点赞逻辑 return res.json({ success: true, msg: 'You liked the post!' }); } catch { return res.json({ success: false, msg: 'Like failed :(' }); } });
- 前端调整like函数,拿到响应后自行控制页面行为,可选整页刷新或者局部展示提示:
async function like(post_id){ const resp = await fetch(`/like/${post_id}`); const result = await resp.json(); // 可选1:整页刷新,走原有flash提示逻辑 window.location.reload(); // 可选2:不刷新页面,局部展示提示(更丝滑) // 自行实现showToast方法把提示插入当前页面即可 // showToast(result.msg); }
方案2:不修改后端逻辑,直接替换fetch请求
如果不想调整后端现有逻辑,就不要用fetch发请求,换成浏览器原生会触发整页跳转的请求方式即可:
- 最简单的方式是把点赞按钮换成a标签,直接跳转对应地址:
<a href="/like/{{post_id}}" class="like-btn">点赞</a> - 也可以用隐藏form表单提交的方式实现,效果和a标签跳转一致。
内容的提问来源于stack exchange,提问作者Nik
相关产品推荐
相关产品推荐

