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

Flutter抛出异常的最佳实践 如何避免Exception前缀重复

问题根因

你代码中每次捕获异常时都会执行throw Exception(e)操作,该操作会把捕获到的原有异常的字符串描述,拼接到新创建的Exception实例的默认前缀Exception: 之后,4层调用链路每层都做一次包装,最终就会出现4个重复的Exception: 前缀。

正确的异常抛出方案

方案1:无额外信息补充时直接使用rethrow重抛

如果捕获异常后不需要追加自定义的错误上下文,只是要把异常继续向上传递,直接用Dart内置的rethrow关键字即可,不会额外包装异常。
修改后的代码示例:

getSomeData () async {
  try {
    await myFunction3();
  } catch (e) {
    // 无额外信息补充直接重抛
    rethrow;
  }
}

Future<void> myFunction3 () async {
  try {
    await myFunction2();
  } catch (e) {
    rethrow;
  }
}

Future<void> myFunction2 () async {
  try {
    await myFunction1();
  } catch (e) {
    rethrow;
  }
}

Future<void> myFunction1() async {
  try {
    await dio.get(/*some parameters*/);
  }
  on DioError catch (e) {
    // 仅在最底层做一次异常转换,不需要额外包装的话也可以直接rethrow DioError
    throw e.error;
  }
  catch (e) {
    rethrow;
  }
}

修改后最终抛出的错误信息就是原生的:SocketException: OS Error: Connection refused, errno = 111, address = 10.12.7.15, port = 39682,不会有多余的前缀。

方案2:需要补充上下文时仅做一次包装

如果需要给异常追加业务相关的提示信息,仅在最上层或者你需要的某一层做一次Exception包装即可,其他层仍然用rethrow:
示例代码:

getSomeData () async {
  try {
    await myFunction3();
  } catch (e) {
    // 仅在最上层加一次自定义信息包装
    throw Exception("获取业务数据失败,底层错误:$e");
  }
}

// 下层所有函数的catch块都直接rethrow,不做额外包装
Future<void> myFunction3 () async {
  try {
    await myFunction2();
  } catch (e) {
    rethrow;
  }
}
// 其余下层函数同理都用rethrow

最终错误信息只会有一个Exception:前缀:Exception: 获取业务数据失败,底层错误:SocketException: OS Error: Connection refused, errno = 111, address = 10.12.7.15, port = 39682

方案3:自定义异常类型规避默认前缀

如果不想用Dart默认的Exception前缀,可以自定义业务异常类:

class AppException implements Exception {
  final String message;
  AppException(this.message);

  // 重写toString方法,不需要额外加前缀
  @override
  String toString() => message;
}

使用时直接抛出AppException("你的错误信息")即可,不会出现重复前缀。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 02:06:03