Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Token拦截器里的onError,使用 dio.interceptors.errorLock.lock() 无效 #877

Closed
JDChi opened this issue Jul 31, 2020 · 7 comments
Closed

Comments

@JDChi
Copy link

JDChi commented Jul 31, 2020

dio 3.0.7

我创建了个Token拦截器,在onError里处理当token过期时,进行刷新的逻辑。

当我只有一个请求时,过程还是正常的,但当有多个请求同时进行时,我按照Example的例子使用了dio.interceptors.errorLock.lock()
但我发现,即使使用了这个,其它请求同样也会因token失效的错误进入onError,导致dio.interceptors.errorLock.lock()多次被调用。似乎这个锁没有用。

它们不是应该在那里阻塞吗?直到我unlock?

@JDChi
Copy link
Author

JDChi commented Jul 31, 2020

I used my own completer to solve this .

    //here
    Future<Null> _lockFuture;

    @override
    onError(DioError error)  {
    if (error.response?.statusCode == 401) {
      RequestOptions options = error.response.request;
   
       //here
       if (dio.interceptors.errorLock.locked) {
          if (_lockFuture != null) {
            await _lockFuture;
          }
        }
     
      if (csrfToken != options.headers["csrfToken"]) {
        options.headers["csrfToken"] = csrfToken;
        return dio.request(options.path, options: options);
      }
      
      dio.lock();
      dio.interceptors.responseLock.lock();
      dio.interceptors.errorLock.lock();
       //here
       var completer = new Completer<Null>();
        _lockFuture = completer.future;

      return tokenDio.get("/token").then((d) {
        options.headers["csrfToken"] = csrfToken = d.data['data']['token'];
      }).whenComplete(() {
        dio.unlock();
        dio.interceptors.responseLock.unlock();
        dio.interceptors.errorLock.unlock();
        //here
        completer.complete();
        _lockFuture = null;

      }).then((e) {
        return dio.request(options.path, options: options);
      });
    }
    return error;
  }));

@JDChi
Copy link
Author

JDChi commented Jul 31, 2020

#590

@wendux
Copy link
Contributor

wendux commented Aug 7, 2020

拦截器锁的作用范围和dio实例是相关的,不同dio实例之间是相互隔离的,建议全局用同一个dio实例。如果业务场景需要创建多个dio实例,可以用你这种方法去同步多个dio实例。

@JDChi
Copy link
Author

JDChi commented Aug 7, 2020

拦截器锁的作用范围和dio实例是相关的,不同dio实例之间是相互隔离的,建议全局用同一个dio实例。如果业务场景需要创建多个dio实例,可以用你这种方法去同步多个dio实例。

你好,我当前是只有一个dio实例的,我用的是单例模式来包裹dio,我在onRequest里调用dio.lock(),确实其它一同发起的request都被lock住了,但在onError里调用dio.interceptors.errorLock.lock(),其它的error照样能进入onError()。

@wendux wendux closed this as completed in 516825f Aug 7, 2020
wendux added a commit that referenced this issue Aug 7, 2020
@wendux
Copy link
Contributor

wendux commented Aug 7, 2020

3.0.10已修复

@supermebing
Copy link

3.0.10已修复
3.0.10还是有问题

@leafney
Copy link

leafney commented Mar 28, 2021

I have been following this issue.

I also encountered this problem in the previous v3.0.10 for 但我发现,即使使用了这个,其它请求同样也会因token失效的错误进入onError , but did not find a better solution.

Seeing that the author updated to v4.0.0 today, it was found to be normal after testing.

my test:

Restarted application in 618ms.
flutter: 发起请求:[ http://172.21.40.40:9999/api/v1/test ],请求数据:[ null ]
flutter: no token,get token first
flutter: 从本地获取到token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2MTY5NDcxMzAsImlzcyI6IlNlY3JldF9WYWxsZXkiLCJ1aWQiOiIxIn0.eQKcW29tQYAqtgxEPLefrMSkgP-GSWPJBFx7OI-dS74
flutter: 后端返回 access_token 已过期的错误码,需要刷新 access_token
flutter: 从本地获取refreshToken: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2MTk1Mzg1OTcsImlzcyI6IlNlY3JldF9WYWxsZXkiLCJ1aWQiOiIxIn0.ndYRA-8CH4xtI-Y246g3NvlO2i4xtLHdFmSoCYNAUKE
flutter: 刷新请求到了新的token eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2MTY5NDcyODEsImlzcyI6IlNlY3JldF9WYWxsZXkiLCJ1aWQiOiIxIn0.HTgYUo41l4tVdUIagguYwJ28IDlgNl6ahhwuiYfcEGM
flutter: 刷新token成功,解锁请求
flutter: 重新发起请求 null
flutter: 发起请求:[ http://172.21.40.40:9999/api/v1/test ],请求数据:[ null ]
flutter: have token,use it
flutter: errData -- 200 -- {code: 200, message: 这是返回的数据, data: {}, error: }
flutter: 正常响应
flutter: 拦截器捕获*正常*返回结果:{"code":200,"message":"这是返回的数据","data":{},"error":""}
flutter: response -- {"code":200,"message":"这是返回的数据","data":{},"error":""}
flutter: success -- 200 -- 这是返回的数据
flutter: 发起请求:[ http://172.21.40.40:9999/api/v1/test ],请求数据:[ null ]
flutter: have token,use it
flutter: errData -- 200 -- {code: 200, message: 这是返回的数据, data: {}, error: }
flutter: 正常响应
flutter: 拦截器捕获*正常*返回结果:{"code":200,"message":"这是返回的数据","data":{},"error":""}
flutter: response2 -- {"code":200,"message":"这是返回的数据","data":{},"error":""}
flutter: 发起请求:[ http://172.21.40.40:9999/api/v1/test ],请求数据:[ null ]
flutter: have token,use it
flutter: errData -- 200 -- {code: 200, message: 这是返回的数据, data: {}, error: }
flutter: 正常响应
flutter: 拦截器捕获*正常*返回结果:{"code":200,"message":"这是返回的数据","data":{},"error":""}
flutter: response3 -- {"code":200,"message":"这是返回的数据","data":{},"error":""}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants