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
相关产品推荐
相关产品推荐

