swift - 使用 SwiftUI 组合刷新 token

标签 swift swiftui combine

我正在尝试在 Swift 5 和适用于 iOS 的组合框架中实现刷新 token 策略。

我不打算使用任何第三方包,只使用框架提供的,`URLSession.dataTaskPublisher`,所以 mu 的目标是:

  • 提出请求
  • 如果请求失败并显示 401,则刷新 auth token (这是另一个请求)
  • 刷新 token 完成后,重试第一个请求
  • 如果失败,则抛出由调用者处理的错误


  • 这是一个非常简单的用例,但似乎很难在 Combine 中实现,这使得它在任何现实生活场景中都很难使用。

    欢迎任何帮助!

    这是我的尝试,不幸的是不起作用
    private func dataTaskPublisherWithAuth(for request: URLRequest) -> URLSession.DataTaskPublisher {
        return session.dataTaskPublisher(for: request)
    
            .tryCatch { error -> URLSession.DataTaskPublisher in
    guard error.errorCode == 401 else {
    throw error
    }
    var components = URLComponents(url: self.baseUrl, resolvingAgainstBaseURL: true)
    components?.path += "/refresh"
    components?.queryItems = [
    URLQueryItem(name: "refresh_token", value: KeychainHelper.RefreshToken),
    ]
    
    let url = components?.url
    var loginRequest = URLRequest(url: url!)
    loginRequest.httpMethod = "GET"
    loginRequest.setValue("application/json", forHTTPHeaderField: "Content-Type")
    
    return session.dataTaskPublisher(for: loginRequest)
    .decode(type: LoginResponse.self, decoder: JSONDecoder())
    .map { result in
    if result.accessToken != nil {
    // Save access token
    KeychainHelper.AccessToken = result.accessToken!
    KeychainHelper.RefreshToken = result.refreshToken!
    KeychainHelper.ExpDate = Date(timeIntervalSinceNow: TimeInterval(result.expiresIn!))
    }
    return result
    }
    .flatMap { data -> URLSession.DataTaskPublisher in
    session.dataTaskPublisher(for: request)
    }
        }.eraseToAnyPublsiher()
    
    }
    

    最佳答案

    您应该使用 .tryCatch Publisher 上的方法 here .这使您可以用另一个发布者替换错误(例如用刷新请求替换错误 401,然后是 map switchToLastest auth 请求)或另一个错误(在这种情况下,如果它不是 401,则只抛出原始错误)。

    请注意,您可能不应该使用 flatMap在这里是因为它与 .flatMapLatest 不同在 Rx 或 .flatmap(.latest)在响应式(Reactive) Swift 中。你想养成使用.map的习惯和 switchToLatest在结合(即苹果决定展平和映射是两个独立的运营商)。如果您不这样做,您将在某些生成多个内部发布者的地方遇到麻烦,例如在您键入时搜索,因为您将获得所有这些,而不是获取最新的内部值,因为网络请求在不确定的时间内完成。

    关于swift - 使用 SwiftUI 组合刷新 token ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59719270/

    相关文章:

    swift - 什么是区分 Swift3 中的 fileprivate 和 private 的好例子

    ios - 设置 UITableViewCell 高度与图像比例成比例

    swift - 在 View 中不可变的一些 View 主体变量/不透明返回

    swift - 为什么 `Publishers.Map`会急切的消费上游值呢?

    swift - 如何检测哪个 SCNNode 被触摸了 ARKit

    ios - CollectionView 添加额外的单元格 "Add more"

    swift - 当 View 可以在 SwiftUI 中使用 Equatable 函数时,为什么我不能在我的 View 中使用它?

    swift - macOS 上的 EnvironmentObject 和 SceneDelegate

    SwiftUI/Combine - 订阅单个发布者的最新值

    ios - SwiftUI从ViewModel访问全局状态