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

应用登录功能实现遇运行时错误,求代码排查与修复

登录功能运行时错误排查与修复方案

问题背景

实现应用登录功能时出现运行时错误,相关前后端JavaScript代码如下,错误表现为触发运行时错误提示,但部分业务提示信息可正常显示。

相关代码

前端代码

const loginUser = async () => {
  // 字段校验
  if (!login.username || !login.password) {
    setError('请填写所有字段');
    return;
  }

  let response = await API.userLogin(login);

  if (
    response.msg === '用户名不匹配' ||
    response.msg === '密码不匹配'
  ) {
    setError('用户名或密码错误');
    return;
  }

  if (response.isSuccess) {
    setError('');

    sessionStorage.setItem(
      'accessToken',
      `Bearer ${response.data.accessToken}`
    );
    sessionStorage.setItem(
      'refreshToken',
      `Bearer ${response.data.refreshToken}`
    );

    setAccount({
      username: response.data.username,
      name: response.data.name,
    });
    isUserAuthenticated(true);
    navigate('/');
  } else {
    setError('出现未知错误!');
  }
};

后端代码

export const loginUser = async (request, response) => {
  try {
    let user = await User.findOne({ username: request.body.username });

    if (!user) {
      return response
        .status(401)
        .json({ msg: '用户名不匹配' });
    }
    let match = await bcrypt.compare(
      request.body.password,
      user.password
    );

    if (!match)
      return response
        .status(401)
        .json({ msg: '密码不匹配' });

    if (match) {
      const accessToken = jwt.sign(
        user.toJSON(),
        process.env.ACCESS_SECRET_KEY,
        { expiresIn: '15m' }
      );
      const refreshToken = jwt.sign(user.toJSON(), process.env.REFRESH_SECRET_KEY);

      const newToken = new Token({ token: refreshToken });
      await newToken.save();

      response.status(200).json({
        accessToken: accessToken,
        refreshToken: refreshToken,
        name: user.name,
        username: user.username,
      });
    }
  } catch (error) {
    console.log(error);
    response
      .status(500)
      .json({ msg: '用户登录时发生错误' });
  }
};

错误排查

  1. 前后端响应格式不匹配:
    • 后端成功登录时未返回isSuccess字段,也未将数据包裹在data对象中,但前端代码尝试判断response.isSuccess并访问response.data,导致response.isSuccess为undefined(进入else分支),且response.data为undefined,触发运行时错误。
  2. 前端未捕获请求异常:
    • API.userLogin如果出现网络错误或非预期响应,await会抛出错误,但前端未用try/catch捕获,直接引发运行时错误。
  3. 错误响应判断逻辑脆弱:
    • 前端直接访问response.msg,若请求返回非JSON格式或网络失败,response不是预期对象,访问msg会报错。

修复方案

后端代码修复:统一响应格式

给所有响应添加isSuccess字段明确标识请求状态,同时将成功数据包裹在data对象中,保持格式一致性:

export const loginUser = async (request, response) => {
  try {
    let user = await User.findOne({ username: request.body.username });

    if (!user) {
      return response
        .status(401)
        .json({ isSuccess: false, msg: '用户名不匹配' });
    }
    let match = await bcrypt.compare(
      request.body.password,
      user.password
    );

    if (!match)
      return response
        .status(401)
        .json({ isSuccess: false, msg: '密码不匹配' });

    const accessToken = jwt.sign(
      user.toJSON(),
      process.env.ACCESS_SECRET_KEY,
      { expiresIn: '15m' }
    );
    const refreshToken = jwt.sign(user.toJSON(), process.env.REFRESH_SECRET_KEY);

    const newToken = new Token({ token: refreshToken });
    await newToken.save();

    response.status(200).json({
      isSuccess: true,
      data: {
        accessToken: accessToken,
        refreshToken: refreshToken,
        name: user.name,
        username: user.username,
      }
    });
  } catch (error) {
    console.log(error);
    response
      .status(500)
      .json({ isSuccess: false, msg: '用户登录时发生错误' });
  }
};

前端代码修复:异常捕获+匹配响应格式

添加try/catch捕获请求异常,根据后端统一的响应格式调整处理逻辑:

const loginUser = async () => {
  // 字段校验
  if (!login.username || !login.password) {
    setError('请填写所有字段');
    return;
  }

  try {
    const response = await API.userLogin(login);

    if (!response.isSuccess) {
      if (response.msg === '用户名不匹配' || response.msg === '密码不匹配') {
        setError('用户名或密码错误');
      } else {
        setError(response.msg || '出现未知错误!');
      }
      return;
    }

    setError('');
    sessionStorage.setItem(
      'accessToken',
      `Bearer ${response.data.accessToken}`
    );
    sessionStorage.setItem(
      'refreshToken',
      `Bearer ${response.data.refreshToken}`
    );

    setAccount({
      username: response.data.username,
      name: response.data.name,
    });
    isUserAuthenticated(true);
    navigate('/');
  } catch (error) {
    // 处理网络错误或请求异常
    setError('网络错误,请稍后重试');
    console.error('登录请求失败:', error);
  }
};

额外说明

如果API.userLogin基于fetch实现,需确保它解析JSON并处理HTTP错误状态码,示例如下:

// 示例API.userLogin实现
const userLogin = async (loginData) => {
  const res = await fetch('/api/login', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(loginData)
  });
  // 处理HTTP错误状态码
  if (!res.ok) {
    const errorData = await res.json().catch(() => ({ msg: '请求失败' }));
    return { isSuccess: false, msg: errorData.msg };
  }
  return res.json();
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 04:17:21