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

Flutter使用Dio请求接口如何处理成功响应与422错误异常

问题原因

原代码存在3个核心问题导致异常未正确处理:

  • 状态码匹配错误:接口约定成功状态码为201,原代码仅判断200状态码,成功场景无法正确命中
  • 参数传递位置错误:POST提交的用户凭证属于请求体内容,原代码错误将参数放在queryParameters(URL拼接参数)中,部分后端框架无法正常读取该位置的POST参数
  • 错误处理逻辑缺失:Dio默认将所有非2xx/3xx的HTTP响应(含422校验错误)抛出为DioError,原catch块未对错误类型做区分,既没有解析422场景下的错误响应体,也没有覆盖网络超时、无连接等其他异常场景,同时原代码存在语法括号未闭合的问题。
调整后代码
userLogin(String password, String mobile) async {
  try {
    String url = "url";
    Dio dio = Dio();
    dio.options.headers = {
      'Accept': 'application/json',
      'Content-Type': 'application/json',
    };
    // POST参数放在data字段作为请求体提交,不要放queryParameters
    var response = await dio.post(url, data: {
      "password": password,
      "mobile": mobile,
    });
    
    // 匹配接口约定的201成功状态码
    if (response.statusCode == 201) {
      return {
        "success": true,
        "data": response.data
      };
    }
  } on DioError catch (e) {
    // 专门处理Dio抛出的网络/HTTP错误
    switch (e.type) {
      case DioErrorType.response:
        // 服务端返回了响应(含422、4xx、5xx状态码)
        int? statusCode = e.response?.statusCode;
        if (statusCode == 422) {
          // 解析422校验错误结构
          Map<String, dynamic> errorData = e.response?.data ?? {};
          String message = errorData['message'] ?? '提交数据校验失败';
          Map<String, dynamic> errors = errorData['errors'] ?? {};
          // 提取首个错误提示用于前端展示
          String firstError = '';
          if (errors.isNotEmpty) {
            firstError = errors.values.first[0];
          }
          return {
            "success": false,
            "code": statusCode,
            "message": firstError.isNotEmpty ? firstError : message,
            "errors": errors
          };
        }
        // 处理其他HTTP状态码错误:401未授权、404资源不存在、500服务端错误等
        return {
          "success": false,
          "code": statusCode,
          "message": '请求失败,请稍后重试'
        };
      case DioErrorType.connectTimeout:
      case DioErrorType.receiveTimeout:
      case DioErrorType.sendTimeout:
        return {
          "success": false,
          "message": '网络连接超时,请检查网络后重试'
        };
      case DioErrorType.other:
        // 无网络、DNS解析失败等场景
        return {
          "success": false,
          "message": '网络连接异常,请检查网络设置'
        };
      default:
        return {
          "success": false,
          "message": '请求失败,请稍后重试'
        };
    }
  } catch (e) {
    // 兜底处理其他非Dio类型的未知异常
    return {
      "success": false,
      "message": '未知异常:${e.toString()}'
    };
  }
}
逻辑说明
  • 成功场景:状态码为201时,返回标记为成功的结构,携带接口返回的业务数据
  • 422校验错误场景:直接解析接口返回的errors字段,提取具体的校验失败原因(比如手机号格式错误、密码错误等)返回给上层业务,可直接用于弹窗提示用户
  • 网络异常场景:覆盖超时、无网络等常见用户端网络问题,返回友好提示
  • 其他异常场景:兜底处理所有未覆盖的错误,避免程序崩溃

注意:如果业务需要保留原始错误结构,可直接返回e.response.data无需额外拆理解析。如果项目中全局配置了Dio的validateStatus参数自定义合法状态码范围,需要同步调整对应判断逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 09:00:56