我有一个应用程序,它在其内部为多个任务提取API数据。
主要API数据请求是为我们的卫生系统中的给定提供者或位置提取约会。 为了使密钥正确,以使提供商ID或位置ID与实际名称匹配,我还从API中提取了该数据,以确保它们是最新的。
我可以使用它,因此网络调用会检查当前的API令牌是否处于活动状态,如果没有激活,则会自动刷新它并重新调用网络数据。一旦确认令牌为当前处于活动状态或正确刷新后,它将返回true。
但是,这3个不同的网络请求异步调用数据,一个将更新API令牌,而另一个尝试这样做,然后API令牌将在不必要的顺序内重复更新。
要解决此问题,我尝试切换到本地化令牌功能,该功能会检查当前令牌是否处于活动状态,如果没有,则将其刷新。它还检查是否已在进行令牌更新,如果这样做,则其他功能也将停止更新。它还会重新调用原始函数,以等待更新的令牌出现。
我遇到的问题是我似乎创建了一个循环,该循环使我的应用程序崩溃,然后才能显示新令牌。本质上,我猜想我需要解决的问题是在重新调用循环之前等待响应,但是我不确定执行此操作的最佳方法。
这是我的令牌检查/刷新代码:
我的模型还具有一个var tokenUpdateUpdateInProgress = false,以便新函数可以在新的更新开始时发出警报。
func isTokenActiveAndRefreshIfNot(_ completion: @escaping (Bool) -> ()) {
print("running tokenActive function")
var returnBool = false
print("tokenUpdateInProgressz: \(tokenUpdateInProgress)")
if tokenUpdateInProgress == false {
print("no other update in progress, start the check here")
tokenUpdateInProgress = true
let resourceListURL = "https://api.carecloud.com/v2/oauth2/token_info"
var request = URLRequest(url:URL(string:resourceListURL)!)
request.addValue("Bearer \(token)", forHTTPHeaderField: "Authorization")
request.httpMethod = "GET"
var json = JSON()
URLSession.shared.dataTask(with: request){ data, response, error in
print("data pull called in isTokenActive")
if let httpResponse = response as? HTTPURLResponse {
print("status code: \(httpResponse.statusCode)")
httpStatusCode = httpResponse.statusCode
}
if httpStatusCode == 200 {
print("token is current, proceed")
tokenUpdateInProgress = false
returnBool = true
json = try! JSON(data: data!)
for (_, _) in json {
if let expiration = json["expires_in"].string {
if let double = Double(expiration) {
let dateTime = Date()
let newDateTime = dateTime.addingTimeInterval(double)
tokenExpiresDateTime = newDateTime
}
}
}
}
if httpStatusCode == 403 || httpStatusCode == 401 {
let downloadGroup = DispatchGroup()
print("token is expired, need to refresh it")
tokenUpdate = false
downloadGroup.enter()
refreshToken({ (tokenRefreshed) in. //this function refreshes my token successfully
if tokenRefreshed == true {
//can do something here if token refresh works correctly
returnBool = true
tokenUpdateInProgress = false
downloadGroup.leave()
downloadGroup.notify(queue: DispatchQueue.main) {
// completion(returnItem)
}
}
})
}
completion(returnBool)
}.resume()
} else if tokenUpdateInProgress == true {
print("token update in progress, re-run check and wait for result")
isTokenActiveAndRefreshIfNot { (result) in //this creates a loop if network not working or token refresh not working for any reason. This loops too fast and leads to a crash.
returnBool = result
}
completion(returnBool)
}
}
所有提取此数据的三个函数是: 1:
func monthSchedule(resourceID: String, locationID: String, page: Int, _ completion: @escaping ([appt]) -> ()){
isTokenActiveAndRefreshIfNot { (tokenUpdated) in
print("token update within monthschedule: \(tokenUpdated)")
}
... runs network pull/API interpretation from token once confirmed ok
}
2:
func pullLocationsList(_ completion: @escaping ([Int: String]) -> ()){
isTokenActiveAndRefreshIfNot { (tokenReady) in
print("token ready for pull location list: \(tokenReady)")
}
... runs network pull/API interpretation from token once confirmed ok
}
3:
func pullResourceList(_ completion: @escaping ([Int: String]) -> ()){
isTokenActiveAndRefreshIfNot { (tokenReady) in
print("token ready for pull resource list: \(tokenReady)")
}
... runs network pull/API interpretation from token once confirmed ok
}