Subclassing Provider and refreshing session automatically(子类化Provider,session的自动刷新)--Moya文档

Subclassing Provider and refreshing session automatically(子类化Provider,session的自动刷新)

基于 Artsy's implementation. 使用RxSwift

class OnlineProvider: RxMoyaProvider {

  // First of all, we need to override designated initializer
  override init(endpointClosure: MoyaProvider.EndpointClosure = MoyaProvider.defaultEndpointMapping,
      requestClosure: MoyaProvider.RequestClosure = MoyaProvider.defaultRequestMapping,
      stubClosure: MoyaProvider.StubClosure = MoyaProvider.neverStub,
      manager: Manager = Alamofire.SessionManager.default,
      plugins: [PluginType] = []) {

      super.init(endpointClosure: endpointClosure, requestClosure: requestClosure, stubClosure: stubClosure, manager: manager, plugins: plugins)
  }

  // Request to fetch and store new XApp token if the current token is missing or expired.
  func XAppTokenRequest() -> Observable {

      var appToken = UserInfo.shared.accessToken

      // If we have a valid token, just return it
      if appToken.isValidAndNotExpired {
          return Observable.just(appToken.token)
      }

      // Do not attempt to refresh a session if we don't have valid credentials
      guard let userId = UserInfo.shared.userId, refreshToken = UserInfo.shared.accessToken.refreshToken else {
          return Observable.just(nil)
      }

      // Create actual refresh request
      let newTokenRequest = super.request(MyService.refreshSession(userId: userId, refreshToken: refreshToken))
          .filterSuccessfulStatusCodes()
          .mapJSON()
          .map { element -> (token: String?, refreshToken: String?, expiryTime: Double?) in
              guard let dictionary = element as? NSDictionary else { return (token: nil, refreshToken: nil, expiryTime: nil) }

              return (token: dictionary["auth_token"] as? String, refreshToken: dictionary["refresh_token"] as? String, expiryTime: dictionary["session_time_valid"] as? Double)
          }
          .doOn { event in
              guard case .next(let element) = event else { return }

              UserInfo.shared.accessToken.token = element.0
              UserInfo.shared.accessToken.refreshToken = element.1
              UserInfo.shared.accessToken.setExpirySecondsLeft(element.2)
          }
          .map { (token, refreshToken, expiry) -> String? in
              return token
          }
          .catchError { e -> Observable in
              guard let error = e as? MoyaError else { throw e }
              guard case .statusCode(let response) = error else { throw e }

              // If we have 401 error - delete all credentials and handle logout
              if response.statusCode == 401 {
                  UserInfo.shared.invalidate()
                  Router.shared.popToLoginScreen()
              }
              throw error
          }

      return newTokenRequest
  }

  // Override request to inject XAppTokenRequest if needed
  override func request(token: MyService) -> Observable {
      let actualRequest = super.request(token)

      return self.XAppTokenRequest().flatMap { _ in
          actualRequest
      }
  }
}

创建自定义provider像往常一样以同样的方式:

let MyServiceProvider = OnlineProvider()

同样 你也可以传递参数

let MyServiceProvider = OnlineProvider(endpointClosure: endpointClosure, plugins: [NetworkLogger()])

总结 这小节的核心:

  1. 自定义Provider
  2. 实现一个具体的session自动刷新的案例

你可能感兴趣的:(Subclassing Provider and refreshing session automatically(子类化Provider,session的自动刷新)--Moya文档)