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

React-Flask-SQLAlchemy项目fetch登录响应直接进入catch报错

问题根因

直接触发fetch进入.catch的核心原因是Promise链中抛出了未捕获的异常,结合代码和现象,90%以上概率是以下两个问题叠加:

  1. JSON解析错误:前端调用res.json()时,后端返回的实际响应体不是合法JSON格式。你贴的后端代码虽然写了jsonify(token),但如果实际运行的代码没有正确序列化(比如服务没重启、漏写jsonify直接返回裸JWT字符串),裸JWT以ey开头,不符合JSON语法要求(JSON字符串必须用双引号包裹),解析时会直接抛出SyntaxError: Unexpected token 'e',该异常会被catch分支捕获。
  2. 跨域拦截:如果后端没有正确配置CORS规则,即使POST请求到达后端完成逻辑执行、生成了token,浏览器也会因为响应头缺少Access-Control-Allow-Origin等必填字段拦截响应,fetch会直接将这类跨域错误抛到catch中。

除此之外,前端代码还有两个必然导致逻辑异常的写法错误,就算解决上述报错也无法正常运行:

  • 第一个then中拿到的res是Fetch API的原始Response实例,响应体还未被解析,直接读取res.nickname永远得到undefined,根本拿不到用户信息。
  • 后端接口仅返回了token字符串,没有返回nickname等用户字段,就算正确解析响应也拿不到对应数据。
修复方案

第一步:修正后端代码

  1. 调整接口返回格式,不要直接返回裸token字符串,返回结构化JSON对象,同时返回需要的用户信息,避免前端二次解析JWT:
@api.route('/login' , methods=['POST']) 
def login_user():

    body = request.get_json()
    user_check_email = body['email'] 
    user_check_password = body['password']
    
    user = User.query.filter_by(email=user_check_email).first()
    if user is None:
        raise APIException('Usuario no encontrado /routes login l 89')

    passwordCheck = bcrypt.checkpw(user_check_password.encode('utf-8'), user.password.encode('utf-8'))
    print('esto es passwordCheck', passwordCheck)
    if passwordCheck is False:
        raise APIException('Clave incorrecta /routes login l 95')

    user_data = {
        "id": user.id,
        'email': user.email,
        'nickname': user.nickname,
        'name': user.name,
        'surname': user.surnames
    }

    token = create_access_token(identity=user_data)
    # 调整返回结构,返回对象而非裸字符串
    return jsonify({
        "access_token": token,
        "user": user_data
    }), 201
  1. 正确配置CORS,避免浏览器跨域拦截。如果使用Flask-CORS,在app初始化位置添加全局配置即可,框架会自动处理OPTIONS预检请求:
from flask_cors import CORS
# 初始化app后添加
CORS(app, supports_credentials=True)
  1. 修改完成后重启后端服务,确保代码更新生效,避免旧代码逻辑仍在运行。

第二步:修正前端fetch逻辑

调整Promise链顺序,先解析响应体,再处理业务判断,不要在Response实例上直接读取业务字段:

login: (email, password) => {
    fetch(`${config.hostname}/api/login`, {
        method: 'POST',
        body: JSON.stringify({email, password}),
        headers: {
            'Content-Type': 'application/json'
        }
    })
    .then(async res => {
        // 先统一解析响应体
        const respData = await res.json();
        if (res.status === 200 || res.status === 201){
            // 从解析后的数据中读取用户信息
            setStore({nombre: respData.user.nickname})
            setStore({userVotes: true})
            setStore({loginEmailPassMatch: false})
            alert("登录成功")
            return respData
        } else {
            setStore({loginEmailPassMatch: true}) 
            // 抛出业务错误,统一进入catch处理
            throw new Error("Usuario o clave incorrectas")
        }
    })
    .then(data => {
        console.log("登录返回数据", data)
        // 从结构化返回中取token存储
        localStorage.setItem("token", data.access_token)
        setStore({token: data.access_token})
    })
    .catch(error => {
        console.log("请求异常", error)
        alert(`登录失败:${error.message}`)
    })
},
验证要点

修改完成后,打开浏览器开发者工具的Network面板,找到login接口:

  • 确认响应状态码为201,响应体是格式正确的JSON
  • 确认响应头中存在Access-Control-Allow-Origin字段,值匹配前端服务域名
  • 确认控制台不再抛出JSON解析或跨域相关的错误

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 19:06:44