使用Fetch发送POST请求后,Node.js中res.redirect与res.render失效问题
问题:Fetch发送POST请求后,Node.js后端的res.redirect/res.render无法生效
我有一段Node.js代码,用于处理来自EJS页面通过Fetch发送的POST请求:
app.post('/signup', jsonParser, async function(req, res) { const email = req.body.email; const password = req.body.password; console.log(`hello`) auth.createUserWithEmailAndPassword(email, password).then(async userCredentials => { const user = userCredentials.user console.log(user.email) await db.collection("users").add({ createdAt: Date.now(), name: req.body.name, email: email, signupmethod: "email", }) .then((docRef) => { console.log("Document written with ID: ", docRef.id); }) .catch((error) => { return console.error("Error adding document: ", error); }); res.redirect(`/dashboard`) }).catch(error => { res.render('signup', {error:error.message}) return console.log(error.message) }) });
发送POST请求的前端代码:
const data = { email: email, password: password, name:name, } fetch("/signup", { method: "POST", headers: {'Content-Type': 'application/json'}, body: JSON.stringify(data) }).then((response) => { console.log(response); })
提交表单后,POST请求已发送,用户也成功登录,但页面没有任何变化。为何成功时无法跳转页面、出错时无法渲染页面?是res存在问题吗?
原因分析
这不是res的问题,核心原因是Fetch属于AJAX异步请求,它不会自动触发浏览器的页面跳转或页面渲染:
- 当后端返回
res.redirect('/dashboard')时,浏览器会返回302重定向状态码,Fetch会自动跟随这个重定向并获取/dashboard的页面内容,但只会把内容存在响应对象里,不会主动替换当前页面。 - 当后端返回
res.render('signup', {error:error.message})时,Fetch会接收到渲染后的HTML字符串,但同样不会自动替换当前页面的内容,所以你看不到错误提示。
解决方案
方案1:后端返回状态信息,前端手动处理
修改后端代码,返回JSON格式的状态数据,由前端决定页面行为:
app.post('/signup', jsonParser, async function(req, res) { const email = req.body.email; const password = req.body.password; try { const userCredentials = await auth.createUserWithEmailAndPassword(email, password); const user = userCredentials.user; console.log(user.email); const docRef = await db.collection("users").add({ createdAt: Date.now(), name: req.body.name, email: email, signupmethod: "email", }); console.log("Document written with ID: ", docRef.id); // 返回成功状态和跳转地址 res.json({ success: true, redirectUrl: '/dashboard' }); } catch (error) { console.log(error.message); // 返回错误状态和错误信息 res.json({ success: false, error: error.message }); } });
修改前端Fetch回调,根据后端返回的信息处理页面跳转或错误提示:
const data = { email: email, password: password, name:name, } fetch("/signup", { method: "POST", headers: {'Content-Type': 'application/json'}, body: JSON.stringify(data) }).then((response) => response.json()) .then((result) => { if (result.success) { // 手动触发页面跳转 window.location.href = result.redirectUrl; } else { // 手动显示错误信息(需在页面中添加对应元素) const errorElement = document.getElementById('error-message'); if (errorElement) { errorElement.textContent = result.error; errorElement.style.display = 'block'; } } }) .catch((err) => { console.error('请求出错:', err); });
同时在signup.ejs页面中添加错误提示元素:
<div id="error-message" style="display: none; color: red;"></div>
方案2:使用传统表单提交(无需Fetch)
如果不需要异步提交的特性,可以直接用HTML表单提交,这样后端的res.redirect和res.render就能正常工作:
修改前端表单代码:
<form action="/signup" method="POST"> <input type="text" name="name" placeholder="姓名" required> <input type="email" name="email" placeholder="邮箱" required> <input type="password" name="password" placeholder="密码" required> <button type="submit">注册</button> <!-- 错误提示区域 --> <% if (error) { %> <div style="color: red;"><%= error %></div> <% } %> </form>
注意:这种方式需要后端配置urlencoded解析器(替换原来的jsonParser):
app.use(express.urlencoded({ extended: true }));
提交表单后,后端的res.redirect会直接触发浏览器跳转,出错时res.render会重新渲染注册页面并显示错误信息。
内容的提问来源于stack exchange,提问作者FattyDev1
相关产品推荐
相关产品推荐

