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
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);
}