You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用res.json(data)返回JSON时直接显示在浏览器而非传给前端JS的问题

问题

在Node.js(Express+MySQL)后端通过res.json(data)返回JSON对象时,浏览器直接显示JSON内容,未被前端原生JavaScript代码接收处理。相关代码如下:

后端Node.js代码

app.post('/register', async (req, res) => {
    db.query('SELECT email FROM users WHERE email = ?', [req.body.mail], async (err, result) => {
        if (err) throw err;
        if (result[0]) {
            console.log('Mail already used') // 此日志正常输出
            var data = {
                status: 'error',
                error: 'This email is already being used'
            }
            res.json(data);
            // 省略后续代码
        }
    })
})

前端原生JavaScript代码

const form = document.getElementById('register')
form.addEventListener('submit', (event) => {
    event.preventDefault()

    const formData = new FormData(form)
    fetch("/register", {
        method: 'POST',
        body: formData
    })
        .then(response => response.json())
        .then(data => {
            document.getElementById('error').style.display = "block"
            document.getElementById('error').innerText = data.error
            console.log(data);
        })
        .catch(error => {
            console.error(error)
        }) 
})

HTML代码

<form id="register" action="/register" method="POST" >
    <div class="txt name">
        <input type="text" name="name" id='name' required>
        <label>name</label>
    </div>
    <div class="txt mail">
        <input type="text" name="mail" id="mail" required>
        <label>Mail</label>
    </div>
    <div class="txt password">
        <input type="password" name="password" id="password" required>
        <label>Password</label>
    </div>
    <div class="txt confirm">
        <input type="password" name="confirm" id="confirm" required>
        <label>Confirm Password</label>
    </div>
    <div class="btn">
        <input type="submit" id="btn" value="Register">
    </div>
</form>

解决方法

核心问题是表单默认提交行为未被有效阻止,导致浏览器直接跳转到action地址并显示响应,而非走异步请求流程。按以下步骤修复:

  1. 确保表单提交事件被正确拦截

    • 确认JS代码在DOM加载完成后执行:将JS代码放在</body>标签前,或用DOMContentLoaded包裹,避免因DOM未加载完成导致事件绑定失败:
      document.addEventListener('DOMContentLoaded', () => {
          const form = document.getElementById('register')
          form.addEventListener('submit', (event) => {
              event.preventDefault();
              // 后续fetch请求代码
          })
      })
      
    • 检查页面是否有其他监听表单提交的代码,避免事件传播被干扰。
  2. 配置后端解析FormData

    • Express默认不处理multipart/form-data类型的请求体(FormData属于此类),需安装multer中间件解析:
      npm install multer
      
      后端代码配置:
      const multer = require('multer');
      const upload = multer(); // 仅解析数据,不保存文件
      
      app.post('/register', upload.none(), async (req, res) => {
          // 此时req.body可正常获取表单字段
          db.query('SELECT email FROM users WHERE email = ?', [req.body.mail], (err, result) => {
              // 原有业务逻辑
          })
      })
      
    • 若未解析FormData,req.body.mail会是undefined,导致查询逻辑异常,影响响应返回。
  3. 验证异步请求是否发送

    • 打开浏览器开发者工具(F12)的「网络」标签,点击注册按钮后,查看是否有/register的POST请求。若无请求,说明事件绑定失败,表单走了默认提交流程。

内容的提问来源于stack exchange,提问作者Pada iOS

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 17:17:43