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

Node.js Express接口无响应:前端Axios无法获取响应状态

问题与解决方案

问题描述

使用Axios的post函数向Node.js Express接口提交multipart表单数据,后端通过Multiparty处理输入字段。接口已成功接收数据并插入数据库,但无法获取响应状态来触发表单重置操作。

原前端代码

let categories = []

const form = document.getElementById("category");
  
const formEvent = form.addEventListener("submit", async (event) => {
  event.preventDefault();
  let cat = new FormData(form);
  cat.append('userId',userId)
  await postCat(cat);
});

const postCat  = async (cat) =>{
   
    await axios.post('http://localhost:8080/api/category-api/addNew/?', 
         cat, {
          headers: {
            'Content-Type': 'multipart/form-data'
          }
        }
      )
         .then( (res) => {
            if ( res.status(200)){
              form.reset();
              document.getElementById('shim').style.display = document.getElementById('msgbx').style.display = "none";
            }  
            else if (!res.status(200)) {
                  return null
              }
          })
          .catch((e) => {
              console.log('ERROR ERROR', e, 'ERROR ERROR')
          })
}

原后端代码

router.post("/addNew/", async (req, res) => {

  let form = new multiparty.Form();

  let pros = [], cons = [];
  let newCategory = { pros, cons }

  await form.parse(req, async (err, fields) => { 
    await Object.keys(fields).forEach((property) => {
      
      if (fields[property].toString().length > 0 && fields[property].toString() !== ' ') {
        if (property.startsWith('pro')) newCategory.pros.push(fields[property].toString())
        else if (property.startsWith('con')) newCategory.cons.push(fields[property].toString())
        else newCategory[property] = fields[property].toString();
      }
      if (property === ('name') && newCategory[property].length === 0) {
        return res.status(400).json({ msg: "Name must be included" });
      }
    }
    )
    categories.push(newCategory)     
    await insertCat(newCategory)           
    await res.status(200).json(categories) 
  })
});

问题分析与修复方案

1. 前端错误修复

  • res.status用法错误:前端Axios响应对象中,status是属性而非方法,正确判断方式是res.status === 200,或者用res.ok(状态码在200-299时为true)。
  • 混合使用await与.then/.catch:统一改用async/await + try/catch写法,逻辑更清晰。
  • 无需手动设置Content-Type:Axios会自动根据FormData对象生成正确的multipart/form-data请求头,手动设置可能缺失边界符,导致后端解析异常。

修改后的前端代码:

let categories = []

const form = document.getElementById("category");
  
form.addEventListener("submit", async (event) => {
  event.preventDefault();
  const cat = new FormData(form);
  cat.append('userId', userId);
  await postCat(cat);
});

const postCat = async (cat) => {
  try {
    const res = await axios.post('http://localhost:8080/api/category-api/addNew/', cat);
    // 正确判断响应状态
    if (res.status === 200 || res.ok) {
      form.reset();
      document.getElementById('shim').style.display = 'none';
      document.getElementById('msgbx').style.display = 'none';
    }
  } catch (e) {
    console.log('ERROR ERROR', e, 'ERROR ERROR');
    // 可在此添加错误提示逻辑
  }
}

2. 后端错误修复

  • form.parse异步处理:form.parse基于回调,外层await无效,需将其包装为Promise,确保等待表单解析完成后再执行后续逻辑。
  • forEach不支持异步:改用for...of循环处理字段,保证异步逻辑正确执行。
  • 避免重复响应:检查name字段为空时,返回响应后需终止后续代码,防止多次发送响应导致服务器错误。

修改后的后端代码:

router.post("/addNew/", async (req, res) => {
  const form = new multiparty.Form();
  const pros = [], cons = [];
  const newCategory = { pros, cons };

  // 将form.parse包装为Promise
  const parseForm = () => {
    return new Promise((resolve, reject) => {
      form.parse(req, (err, fields) => {
        if (err) reject(err);
        else resolve(fields);
      });
    });
  };

  try {
    const fields = await parseForm();
    
    // 用for...of替代forEach,支持异步操作
    for (const property of Object.keys(fields)) {
      const value = fields[property].toString();
      if (value.length > 0 && value.trim() !== '') {
        if (property.startsWith('pro')) {
          newCategory.pros.push(value);
        } else if (property.startsWith('con')) {
          newCategory.cons.push(value);
        } else {
          newCategory[property] = value;
        }
      }

      // 检查name字段是否为空
      if (property === 'name' && newCategory.name?.length === 0) {
        return res.status(400).json({ msg: "Name must be included" });
      }
    }

    categories.push(newCategory);
    await insertCat(newCategory);
    res.status(200).json(categories);
  } catch (err) {
    console.error('Form parse error:', err);
    res.status(500).json({ msg: "Server error" });
  }
});

关键说明

  • 前端移除手动设置的请求头后,Axios会自动生成带正确边界符的multipart/form-data头,确保后端能正常解析。
  • 后端通过Promise包装form.parse,解决了异步回调导致的响应时机问题,保证请求等待解析完成后再返回结果。
  • for...of循环替代forEach,确保字段处理时的异步逻辑能正确等待执行。

内容的提问来源于stack exchange,提问作者Oss Kell

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 15:39:59