I am using Moya to handle HTTP operations and normally I have an refreshToken()
. I am checking token if expired or not when a request is about happen but the problem is there can be a scenarios that more than one requests. If they are chained with nested types it is not a problem however, it is not likely all the time.
To be more clear lets say I have request1()
and request2()
and assume that they execute separate operations and can be triggered anytime(for instance one is called in a viewDidLoad()
, other one is called in another viewDidLoad()
). when this happens and if the token is expired, my refresh request fails. (statusCode: 400)
So, my question is, how can I make provider to wait refresh()
operation get done?I mean by provider is other endpoints. I want them to wait refresh()
endpoint if it is on.
I will be very appreciated if you suggest a way that will make this easier.
I just set an variable called isTokenRefreshing
true when i start the refresh()
operation and checked it before making a request. If it was true I stored all the requests in an array and when the refresh()
is finished I executed another function which basically makes all the stored requests in a for loop
.
If anyone wants to see the code I can share. Just let me know.
EDIT
This where I, NetworkManager
, handle all my requests. It is in an Singleton class
.
private var awaitingRequests : [NetworkAPI] = []
func makeRequest(_ request: NetworkAPI){
if (Token.sharedInstance.isTokenRefreshing && request.requiresToken) {
self.awaitingRequests.append(request)
return
}
self.provider.request(){ result in ... }
}
func executeWaitedRequests(){
for request in self.awaitingRequests {
self.makeRequest(request)
}
}
NetworkAPI
is main enum
that I hold my endpoint cases
. See the Moya
documents if you do not what I am talking about.
And this is where I handle my Token
operations.
class Token {
static let sharedInstance = Token()
private init(){}
var isTokenRefreshing: Bool = false
func refresh(_ completion: @escaping ()->()){
self.isTokenRefreshing = true
print("refreshing token")
let queue = DispatchQueue(label: "com.asd.ads.makeRequest", attributes: DispatchQueue.Attributes.concurrent)
queue.sync(flags: .barrier, execute: {
NetworkManager.shared.makeRequest(.refresh(), completionHandler: { (success, error) in
self.isTokenRefreshing = false
if success{
completion()
NetworkManager.shared.executeWaitedRequests()
}
print("refrehing ended!")
})
})
}
}