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

Axios Post请求后端接收成功但then/catch回调未触发问题排查

问题描述

开发简易React应用时,设置3个输入框分别采集name、lastName、googleId字段,通过onChange事件结合React Hooks管理输入状态,用户点击提交按钮时,会将输入数据发送至Express后端。目前点击按钮后后端控制台可正常打印请求体,输入的字段内容均能被正确接收。按照代码逻辑,.then()回调执行后应当无刷新渲染新增的用户条目,但当前必须手动刷新页面才能看到新提交的用户数据,.then()回调始终未触发导致功能失效,排查数小时尝试多种方案(包括改用fetch实现请求)都无法解决.then()和.catch()均不触发的问题。

React 前端代码

import React from "react";
import Axios from "axios";


function App(){
    const [listOfUsers, setListOfUsers] = React.useState([])
    const [name, setName] = React.useState("");
    const [lastName, setLastName] = React.useState("");
    const [googleId, setGoogleId] = React.useState("");

    React.useEffect(()=>{
        Axios.get("http://localhost:3001/getUsers").then((response)=>{
            console.log(response);
            setListOfUsers(response.data);
        });
    }, []);

 
    /*function createUser(){
        fetch("http://localhost:3001/createUser", {
            method: "POST",
            headers: {
                "Content-Type": "application/x-www-form-urlencoded"
            },
            body: new URLSearchParams({
                name: name,
                lastName: lastName,
                googleId: googleId
            })  
        }).then(res=>{
            console.log("WHY");
            console.log(res);
        });
    }*/

    console.log("what");
    function createUser(){
        console.log("what"); /* This prints */
        console.log(name); /*This prints the variable name correctly */
        const response = Axios.post("http://localhost:3001/createUser", 
            new URLSearchParams({          
                name: name, 
                lastName: lastName, 
                googleId:googleId
            }), {headers:{"Content-Type":"application/x-www-form-urlencoded"}}
        )
        .then((response)=>{
            console.log("whast");
            console.log("why is this not printing");
            setListOfUsers(...listOfUsers, {name:name, lastName:lastName, googleId:googleId})
            console.log(response);
        }) /* Nothing in the then response */
        .catch((error)=>{
            console.log(error.resonse); /*Nothing here either */
        });
        console.log("hey im done") /* This prints */
    } 


    return (
        <div className="usersDisplay">
            {
                listOfUsers.map((user)=>{
                    return (<h1 key={Math.random()}>Name:{user.name}</h1>)
                })
            }

            <div>
                <input type="text" name="name" onChange={(event)=>{setName(event.target.value)}} placeholder="Name..." value={name}/>
                <input type="text" name="lName" onChange={(event)=>{setLastName(event.target.value)}} placeholder="LastName..." value={lastName}/>
                <input type="text" name="id" onChange={(event)=>{setGoogleId(event.target.value)}} placeholder="GoogleId..." value={googleId}/>
                <button onClick={createUser}>Create User</button>
            </div>
        </div>
    )
};


export { App };

Express 后端代码

const express = require("express");
const bodyParser = require("body-parser");
const mongoose = require("mongoose");
const cors = require("cors");

const app = express();

app.use(bodyParser.urlencoded({extended:true}));
app.use(cors());

/*mongoose.connect("mongodb+srv://{hiddenlogin}I@cluster0.87hm5lv.mongodb.net/?testretryWrites=true&w=majority")*/
mongoose.connect("mongodb+srv://{hiddenlogin}@cluster0.87hm5lv.mongodb.net/?retryWrites=true&w=majority")

const userSchema = new mongoose.Schema({
    name: String,
    lastName: String,
    googleId: String,
    blogs: [],
    likedPosts: []
});
  
const blogSchema = new mongoose.Schema({
    name: String,
    googleId: String,
    likes: Number,
    authorFirst: String,
    authorLast: String,
    content: String,
    cutDownContent: String
})

    
const Blog = new mongoose.model("Blog", blogSchema);

const User = new mongoose.model("User", userSchema);

app.get("/getUsers", (req, res)=>{
    User.find({}, (err, results)=>{
        if (err){res.json(err)};
        res.json(results);
    });
});

app.post("/createUser", async (req, res)=>{
    console.log(req.body);
    const newUser = new User({
        name: req.body.name,
        lastName: req.body.lastName,
        googleId: req.body.googleId,
        blogs: [],
        likedPosts: []
    });
    await newUser.save();
    res.json({"sucess":true});
    console.log("Wow!");
});

app.listen(3001, ()=>{
    console.log("Listening on port 3001");
});
问题根因
  1. 后端接口存在重复发送响应的隐患:/getUsers接口中错误分支执行res.json(err)后没有终止逻辑,会继续执行后续的res.json(results),触发Cannot set headers after they are sent to the client错误,导致服务端连接异常中断,前端Axios请求长期处于pending状态,既不会触发resolve也不会触发reject,直接造成.then、.catch都不执行。
  2. 前端catch回调存在拼写错误:error.resonse应为error.response,就算请求出错进入catch分支,也无法正常打印错误日志,干扰排查方向。
  3. 前端状态更新写法错误:setListOfUsers(...listOfUsers, 新用户)缺少数组包裹,就算.then正常触发,也无法正确更新用户列表。
  4. 后端POST接口未做异常捕获,数据库操作出错时会直接导致请求挂起,无任何响应返回。
  5. 列表渲染使用Math.random()作为key,会导致React渲染异常。
修复方案

1. 修复后端接口逻辑

  • 所有响应发送后添加return终止逻辑,避免重复发送响应头
  • 给POST接口添加try/catch异常捕获
  • 等待数据库连接成功后再启动服务,避免连接异常导致请求挂起
  • 新建用户成功后直接返回完整用户数据,方便前端使用
const express = require("express");
const bodyParser = require("body-parser");
const mongoose = require("mongoose");
const cors = require("cors");

const app = express();

app.use(bodyParser.urlencoded({extended:true}));
app.use(cors());

const userSchema = new mongoose.Schema({
    name: String,
    lastName: String,
    googleId: String,
    blogs: [],
    likedPosts: []
});
  
const blogSchema = new mongoose.Schema({
    name: String,
    googleId: String,
    likes: Number,
    authorFirst: String,
    authorLast: String,
    content: String,
    cutDownContent: String
})

    
const Blog = new mongoose.model("Blog", blogSchema);
const User = new mongoose.model("User", userSchema);

app.get("/getUsers", (req, res)=>{
    User.find({}, (err, results)=>{
        if (err){
            return res.status(500).json(err)
        }
        return res.json(results);
    });
});

app.post("/createUser", async (req, res)=>{
    try {
        console.log(req.body);
        const newUser = new User({
            name: req.body.name,
            lastName: req.body.lastName,
            googleId: req.body.googleId,
            blogs: [],
            likedPosts: []
        });
        await newUser.save();
        console.log("Wow!");
        return res.json({"success":true, data: newUser});
    } catch (err) {
        console.log("创建用户失败", err);
        return res.status(500).json(err);
    }
});

// 等数据库连接成功再启动服务
mongoose.connect("mongodb+srv://{hiddenlogin}@cluster0.87hm5lv.mongodb.net/?retryWrites=true&w=majority")
.then(()=>{
    console.log("数据库连接成功");
    app.listen(3001, ()=>{
        console.log("Listening on port 3001");
    });
})
.catch(err=>{
    console.log("数据库连接失败", err);
})

2. 修复前端逻辑

  • 修正catch回调的拼写错误
  • 修正列表状态更新的写法,使用函数式更新避免闭包拿到旧状态
  • 修正列表渲染的key,优先使用数据库生成的唯一_id
import React from "react";
import Axios from "axios";


function App(){
    const [listOfUsers, setListOfUsers] = React.useState([])
    const [name, setName] = React.useState("");
    const [lastName, setLastName] = React.useState("");
    const [googleId, setGoogleId] = React.useState("");

    React.useEffect(()=>{
        Axios.get("http://localhost:3001/getUsers").then((response)=>{
            console.log(response);
            setListOfUsers(response.data);
        }).catch(err=>{
            console.log("获取用户列表失败", err.response);
        });
    }, []);

    function createUser(){
        Axios.post("http://localhost:3001/createUser", 
            new URLSearchParams({          
                name: name, 
                lastName: lastName, 
                googleId:googleId
            }), {headers:{"Content-Type":"application/x-www-form-urlencoded"}}
        )
        .then((response)=>{
            console.log("创建用户成功", response);
            // 函数式更新状态,避免闭包问题
            setListOfUsers(prev => [...prev, {
                name,
                lastName,
                googleId,
                _id: response.data.data._id
            }])
            // 提交成功后清空输入框
            setName("");
            setLastName("");
            setGoogleId("");
        })
        .catch((error)=>{
            // 修正拼写错误
            console.log("创建用户失败", error.response);
        });
    } 


    return (
        <div className="usersDisplay">
            {
                listOfUsers.map((user)=>{
                    // 优先用用户_id作为key,避免随机数导致渲染异常
                    return (<h1 key={user._id}>Name:{user.name} {user.lastName}</h1>)
                })
            }

            <div>
                <input type="text" name="name" onChange={(event)=>{setName(event.target.value)}} placeholder="Name..." value={name}/>
                <input type="text" name="lName" onChange={(event)=>{setLastName(event.target.value)}} placeholder="LastName..." value={lastName}/>
                <input type="text" name="id" onChange={(event)=>{setGoogleId(event.target.value)}} placeholder="GoogleId..." value={googleId}/>
                <button onClick={createUser}>Create User</button>
            </div>
        </div>
    )
};


export { App };

修改完成后重启前后端服务,即可正常触发.then回调,提交后无需刷新页面即可看到新增的用户条目。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.02 06:06:48