onError method

  1. @override
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
void onError(DioError err, ErrorInterceptorHandler handler) async {
  _dio.interceptors.errorLock.lock();
  if (!isRetriable(err)) {
    _dio.interceptors.errorLock.unlock();
    handler.next(err);
    return;
  }
  try {
    _dio.interceptors.requestLock.lock();
    final options = err.response?.requestOptions;
    final request = err.requestOptions;
    final token = await _tokenStore.fromStore();
    final refreshToken = token.refreshToken;
    if (options == null || refreshToken == null) {
      handler.next(err);
      return;
    }

    if (request.headers["Authorization"] != "Bearer ${token.accessToken}") {
      // tokens were refreshed by another API request.
      print(
          "just retry ${options.path} since access token was already refreshed by another request.");
      await _dio.fetch(options);
      return;
    }
    final tokenResponse = await _kauthApi.refreshAccessToken(refreshToken);
    await _tokenStore.toStore(tokenResponse);
    print("retry ${options.path} after refreshing access token.");
    await _dio.fetch(options);
    return;
  } catch (e) {
    if (e is KakaoAuthException ||
        e is KakaoApiException && e.code == ApiErrorCause.INVALID_TOKEN) {
      await _tokenStore.clear();
    }
    handler.next(err);
    return;
  } finally {
    _dio.interceptors.requestLock.unlock();
    _dio.interceptors.errorLock.unlock();
  }
}