onError method
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 {
final options = err.response?.requestOptions;
final request = err.requestOptions;
final token = await _tokenManagerProvider.manager.getToken();
if (!isRetryable(err) || options == null || token == null) {
handler.next(err);
return;
}
try {
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.");
var response = await _dio.fetch(options);
handler.resolve(response);
return;
}
_dio.lock();
_dio.interceptors.errorLock.lock();
final newToken = await _kauthApi.refreshAccessToken(token);
options.headers["Authorization"] = "Bearer ${newToken.accessToken}";
_dio.unlock();
_dio.interceptors.errorLock.unlock();
print("retry ${options.path} after refreshing access token.");
var response = await _dio.fetch(options);
handler.resolve(response);
} catch (error) {
if (_isTokenError(error)) {
await _tokenManagerProvider.manager.clear();
}
if (error is DioError) {
handler.reject(error);
} else {
handler.reject(DioError(requestOptions: options, error: error));
}
} finally {
// The lock must be unlocked because errors may occur while the lock is locked.
_dio.unlock();
_dio.interceptors.errorLock.unlock();
}
}