我在用https://github.com/p2/OAuth2 https://github.com/p2/OAuth2用于通过 OAuth2 连接到我的应用程序的后端,效果非常好。
我遇到的问题是,当访问令牌过期并且同时发生多个请求时,其中一些请求会失败。
并行请求可以从应用程序的不同部分触发。例如,当应用程序启动时,当前位置将发送到服务器并下载事件列表。
确保第一个刷新令牌请求仍在运行时不会发出第二个刷新令牌请求的最佳方法是什么?
找到您的令牌生命周期并设置缓冲区,例如 1-2 分钟和
如果您的 token 需要刷新,请在 token 刷新时保存所有请求。之后执行所有保存的所有请求。您可以使用 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!
}
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)