当前位置:  开发笔记 > 编程语言 > 正文

使用Swift p2 / OAuth2的OAuth2访问令牌的并行刷新请求

如何解决《使用Swiftp2/OAuth2的OAuth2访问令牌的并行刷新请求》经验,为你挑选了1个好方法。

我正在使用https://github.com/p2/OAuth2通过OAuth2连接到我的应用程序的后端,效果很好。

我遇到的问题是,当访问令牌到期并且多个请求同时发生时,其中一些失败。

可以从应用程序的不同部分触发并行请求。例如,启动应用程序时,当前位置将发送到服务器,并下载事件列表。

确保第一个仍在运行时没有第二个刷新令牌请求的最佳方法是什么?



1> Vicaren..:

查找令牌寿命,并设置缓冲区(例如1-2分钟),如果令牌需要刷新,请在令牌刷新时保存所有请求。之后,执行所有保存的所有请求。您可以使用DispatchQueue和DispatchWorkItem进行此操作。

下面的示例代码。

final class Network: NSObject {

    static let shared = Network()

    private enum Constants {
        static let tokenRefreshDiffrenceMinute = 1
        static let tokenExpireDateKey = "tokenExpireDate"
    }

    private(set) var tokenExpireDate: Date! {
        didSet {
            UserDefaults.standard.set(tokenExpireDate, forKey: Constants.tokenExpireDateKey)
        }
    }

    public override init() {
        super.init()

        if let date = UserDefaults.standard.object(forKey: Constants.tokenExpireDateKey) as? Date {
            tokenExpireDate = date
            print("Token found!")
        }
        else {
            print("Token not found!")
            isTokenRefreshing = true
            getToken {
                self.isTokenRefreshing = false
                self.executeAllSavedRequests()
            }
        }
    }


    private var isTokenRefreshing = false
    private var savedRequests: [DispatchWorkItem] = []

    func request(url: String, params: [String: Any], result: @escaping (String?, Error?) -> Void) {

        // isTokenRefreshing save all requests
        if isTokenRefreshing {

            saveRequest {
                self.request(url: url, params: params, result: result)
            }

            return
        }

        // if token expire
        if getMinutesFrom2Dates(Date(), tokenExpireDate) < Constants.tokenRefreshDiffrenceMinute {

            // open this flag for we need wait refresh token
            isTokenRefreshing = true

            // save current request too
            saveRequest {
                self.request(url: url, params: params, result: result)
            }


            // get token
            self.getToken { [unowned self] in
                self.isTokenRefreshing = false
                self.executeAllSavedRequests()
            }
        } else {
            //Alamofire.request ...

            DispatchQueue.global().asyncAfter(deadline: .now() + 2) {
                DispatchQueue.main.async(execute: {
                    result(url, nil)
                })
            }
        }
    }

    private func saveRequest(_ block: @escaping () -> Void) {
        // Save request to DispatchWorkItem array
        savedRequests.append( DispatchWorkItem {
            block()
        })
    }

    private func executeAllSavedRequests() {
        savedRequests.forEach({ DispatchQueue.global().async(execute: $0) })
        savedRequests.removeAll()
    }

    private func getToken(completion: @escaping () -> Void) {
        print("Token needs a be refresh")
        // Goto server and update token
        DispatchQueue.global().asyncAfter(deadline: .now() + 1) { [unowned self] in
            DispatchQueue.main.async(execute: { [unowned self] in
                self.tokenExpireDate = Date().addingTimeInterval(120)
                print("Token refreshed!")
                completion()
            })
        }
    }

    private func getMinutesFrom2Dates(_ date1: Date, _ date2: Date) -> Int {
        return Calendar.current.dateComponents([.minute], from: date1, to: date2).minute!
    }
}

推荐阅读
个性2402852463
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有