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

Dio拦截器onError抛自定义异常无法捕获、执行卡住问题

问题场景

使用Dio网络框架时,在拦截器的onError回调中编写逻辑,希望针对不同错误场景抛出自定义异常,对应onError实现代码如下:

@override
  Future<void> onError(DioError err, ErrorInterceptorHandler handler) async {

    switch (err.type) {
      case DioErrorType.connectTimeout:
      case DioErrorType.sendTimeout:
      case DioErrorType.receiveTimeout:
        throw DeadlineExceededException(err.requestOptions);
      case DioErrorType.response:
        switch (err.response?.statusCode) {
          case 400:
            throw BadRequestException(err.requestOptions);
          case 401:
            throw UnauthorizedException(err.requestOptions);

          case 404:
            throw NotFoundException(err.requestOptions);
          case 409:
            throw ConflictException(err.requestOptions);
          case 500:
            throw InternalServerErrorException(err.requestOptions);
        }
        break;
      case DioErrorType.cancel:
        break;
      case DioErrorType.other:
        throw NoInternetConnectionException(err.requestOptions);
    }
   // super.onError(err, handler);
     return handler.next(err);
  }
异常现象

实际运行时,程序执行到拦截器抛出自定义异常的步骤就卡住,外层请求方法的try/catch块无法捕获到对应异常。业务侧请求方法代码如下:

static requestMyJobs() async {
    try {
      print('---------job calling api---------');
      var response = await ApiBase.dio.get(ApiLinks.getMyJobsLink);
      print('Status code ${response.statusCode}');
      var jocodedData = response.data['data'];
      return jocodedData.map<MyJobs>((json) => MyJobs.fromJson(json)).toList();
    } on UnauthorizedException catch (f) {
      print("-Exception----------------");

    }
  }

requestMyJobs方法中已经添加了UnauthorizedException的捕获逻辑,期望捕获接口返回401状态码时抛出的未授权异常,但始终无法进入捕获分支,程序无响应。

问题原因
  • Dio拦截器的错误流转不支持直接在onError回调中通过throw向外层抛自定义异常,拦截器的错误、响应、请求传递完全依赖handler对象的对应方法控制,直接throw的异常会被拦截器内部的调度逻辑吞掉,不会传递到外层调用方。
  • 代码逻辑存在冲突:匹配到错误分支执行throw后,末尾的handler.next(err)仍会将原始的DioError继续向拦截器链下游传递,异常流转逻辑混乱,最终导致程序卡住。
  • 注释掉了super.onError(err, handler)的默认实现,部分未匹配到分支的错误没有正确的流转出口。
解决方案
  1. 所有需要向外层传递的自定义异常,不要直接throw,而是通过handler.reject(自定义异常)方法传递,该方法会将异常沿着Dio的调用链正常抛出,能被外层try/catch捕获。
  2. 每个错误分支处理完成后直接返回,不要在分支处理完后再统一调用handler.next(err),避免错误重复传递。
  3. 未匹配到自定义处理逻辑的错误分支,正常调用父类onError方法或执行handler.next(err)交给后续逻辑处理。

修正后的拦截器onError代码示例:

@override
Future<void> onError(DioError err, ErrorInterceptorHandler handler) async {
  switch (err.type) {
    case DioErrorType.connectTimeout:
    case DioErrorType.sendTimeout:
    case DioErrorType.receiveTimeout:
      // 用reject传递自定义异常
      return handler.reject(DeadlineExceededException(err.requestOptions));
    case DioErrorType.response:
      switch (err.response?.statusCode) {
        case 400:
          return handler.reject(BadRequestException(err.requestOptions));
        case 401:
          return handler.reject(UnauthorizedException(err.requestOptions));
        case 404:
          return handler.reject(NotFoundException(err.requestOptions));
        case 409:
          return handler.reject(ConflictException(err.requestOptions));
        case 500:
          return handler.reject(InternalServerErrorException(err.requestOptions));
      }
      // 未匹配到状态码的响应错误,继续向下传递
      break;
    case DioErrorType.cancel:
      break;
    case DioErrorType.other:
      return handler.reject(NoInternetConnectionException(err.requestOptions));
  }
  // 不需要特殊处理的错误,调用父类逻辑+传递给下游
  super.onError(err, handler);
  return handler.next(err);
}

注意:自定义异常类建议继承DioError,可以兼容Dio内部所有错误处理逻辑,避免出现类型不兼容问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 08:06:21