onError method

  1. @override
Future<void> onError(
  1. DioError err,
  2. ErrorInterceptorHandler handler
)

The callback will be executed on error.

If you want to continue the error , call handler.next.

If you want to complete the response with some custom data directly, you can resolve a Response object with handler.resolve and other error interceptor(s) will be skipped.

If you want to complete the response with an error message directly, you can reject a DioError object with handler.reject, and other error interceptor(s) will be skipped.

Implementation

@override
Future<void> onError(DioError err, ErrorInterceptorHandler handler) async {
  if (null == err.response) {
    return handler.reject(err);
  }

  //http 400
  if (HttpStatus.badRequest != err.response!.statusCode) {
    return handler.reject(err);
  }

  final errorMessage = ErrorMessage.fromJson(jsonDecode(err.response!.data));

  final message = errorMessage.error.message!;

  if (!message.contains('OAuth')) {
    return handler.reject(err);
  }

  print('AuthToken错误');

  final currentTime = DateTime.now().millisecondsSinceEpoch;

  if (null == getToken()) {
    return handler.reject(err);
  }

  final option = err.requestOptions;

  //防止连续多个OAuth错误 导致重复刷新token
  if ((currentTime - _refreshTokenLastTime) > _refreshTokenMinInterval) {
    print('需要刷新AuthToken');

    final currentAccount = accountGetter.call()!;

    bool hasError = false;

    await auth.refreshAuthToken(currentAccount.refreshToken).then((result) {
      accountUpdater.call(result);
      _refreshTokenLastTime = currentTime;

      option.headers[authHeaderName] = result.accessToken;
    }).catchError((e) {
      print('刷新AuthToken失败');
      print((e as DioError).response!.data);
      hasError = true;
    });

    QueuedInterceptorsWrapper();
    if (hasError) {
      return handler.reject(err);
    }
  }

  final response = await httpClient.request(
    option.path,
    data: option.data,
    queryParameters: option.queryParameters,
    cancelToken: option.cancelToken,
    options: Options(
      method: option.method,
      headers: option.headers,
      contentType: option.contentType,
    ),
  );

  return handler.resolve(response);
}