如何根据重试申请响应发布集团状态?

发布于 2025-02-12 00:01:29 字数 2830 浏览 0 评论 0原文

我尝试在我的应用程序中实现刷新令牌,因此每次请求时,dio都会检查响应,如果响应状态代码为401,则它将刷新访问令牌和重试该请求,

Future onError(DioError dioError, ErrorInterceptorHandler handler) async {
print(dioError.response!.statusCode);
int? responseCode = dioError.response!.statusCode;
String? oldAccessToken = _sharedPreferencesManager
    .getString(SharedPreferencesManager.keyAccessToken);
if (oldAccessToken != null && responseCode == 401) {
  _dio.interceptors.responseLock.lock();
  _dio.interceptors.responseLock.lock();

  String? refreshToken = _sharedPreferencesManager
      .getString(SharedPreferencesManager.keyRefreshToken);
  Map<String, dynamic> refreshTokenBody = {
    'grant_type': 'refresh_token',
    'refresh_token': refreshToken
  };
  ApiRepository apiAuthRepository = ApiRepository();
  LoginModel token =
      await apiAuthRepository.postRefreshAuth(refreshTokenBody);
  if (token.success) {
    String newAccessToken = token.data.accessToken;
    String newRefreshToken = token.data.refreshToken;
    await _sharedPreferencesManager.putString(
        SharedPreferencesManager.keyAccessToken, newAccessToken);
    await _sharedPreferencesManager.putString(
        SharedPreferencesManager.keyRefreshToken, newRefreshToken);
  }
  RequestOptions options = dioError.response!.requestOptions;
  options.headers.addAll({'requirestoken': true});
  _dio.interceptors.requestLock.unlock();
  _dio.interceptors.responseLock.unlock();
  handler.next(dioError);
  return _dio.request(options.path,
      options: Options(headers: options.headers));
} else {
  super.onError(dioError, handler);
}
}

如果我的bloc中的问题在我的bloc中,则我尝试使用已过期的访问令牌访问API(如果我尝试使用Active Access令牌,没有问题),DIO通过刷新和重试该请求可以正常工作,但是我的BLOC仅根据该请求发出加载/故障状态第一回应的结果,任何想法如何解决?

Future<void> mapEventToState(
  Emitter<DashboardState> emit, DashboardEvent event) async {
emit(DashboardLoading());
DashboardModel getMe = await apiAuthRepository.getMeUser();
if (!getMe.success) {
  emit(DashboardFailure(getMe.message));
}
emit(
  DashboardSuccess(),
);
}

这是我实施集团的方式

BlocProvider<DashboardBloc>(
      create: (_) => _dashboardBloc,
      child: BlocListener<DashboardBloc, DashboardState>(
        listener: (context, state) {
          if (state is DashboardFailure)
            ScaffoldMessenger.of(context).showSnackBar(SnackBar(
              content: Text(state.error),
            ));
        },
        child: BlocBuilder<DashboardBloc, DashboardState>(
          builder: (context, state) {
            if (state is DashboardSuccess)
              return ListView(..);
            else if (state is DashboardLoading)
              return Center(child: const CircularProgressIndicator());
            else
              print(state);
            return Container();

I tried to implement a refresh token in my app, so every time I do request, dio will check the response, if the response status code is 401 then it will refresh the access token and retry the request

Future onError(DioError dioError, ErrorInterceptorHandler handler) async {
print(dioError.response!.statusCode);
int? responseCode = dioError.response!.statusCode;
String? oldAccessToken = _sharedPreferencesManager
    .getString(SharedPreferencesManager.keyAccessToken);
if (oldAccessToken != null && responseCode == 401) {
  _dio.interceptors.responseLock.lock();
  _dio.interceptors.responseLock.lock();

  String? refreshToken = _sharedPreferencesManager
      .getString(SharedPreferencesManager.keyRefreshToken);
  Map<String, dynamic> refreshTokenBody = {
    'grant_type': 'refresh_token',
    'refresh_token': refreshToken
  };
  ApiRepository apiAuthRepository = ApiRepository();
  LoginModel token =
      await apiAuthRepository.postRefreshAuth(refreshTokenBody);
  if (token.success) {
    String newAccessToken = token.data.accessToken;
    String newRefreshToken = token.data.refreshToken;
    await _sharedPreferencesManager.putString(
        SharedPreferencesManager.keyAccessToken, newAccessToken);
    await _sharedPreferencesManager.putString(
        SharedPreferencesManager.keyRefreshToken, newRefreshToken);
  }
  RequestOptions options = dioError.response!.requestOptions;
  options.headers.addAll({'requirestoken': true});
  _dio.interceptors.requestLock.unlock();
  _dio.interceptors.responseLock.unlock();
  handler.next(dioError);
  return _dio.request(options.path,
      options: Options(headers: options.headers));
} else {
  super.onError(dioError, handler);
}
}

The problem is in my Bloc, if I tried to access the API with the expired access token (If I tried using an active access token there is no problem), the dio works fine by refreshing and retrying the request, but my bloc only emits a Loading/Failure State based on the result of the first response, any idea how to solve it?

Future<void> mapEventToState(
  Emitter<DashboardState> emit, DashboardEvent event) async {
emit(DashboardLoading());
DashboardModel getMe = await apiAuthRepository.getMeUser();
if (!getMe.success) {
  emit(DashboardFailure(getMe.message));
}
emit(
  DashboardSuccess(),
);
}

And here is how I implement the Bloc

BlocProvider<DashboardBloc>(
      create: (_) => _dashboardBloc,
      child: BlocListener<DashboardBloc, DashboardState>(
        listener: (context, state) {
          if (state is DashboardFailure)
            ScaffoldMessenger.of(context).showSnackBar(SnackBar(
              content: Text(state.error),
            ));
        },
        child: BlocBuilder<DashboardBloc, DashboardState>(
          builder: (context, state) {
            if (state is DashboardSuccess)
              return ListView(..);
            else if (state is DashboardLoading)
              return Center(child: const CircularProgressIndicator());
            else
              print(state);
            return Container();

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文