3

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.

Faruk
  • 2,269
  • 31
  • 42
  • Everytime before you call a request you want to check if refresh token is expired or not. If it is, then you receive refresh token through a service and then make the request. Just to be sure, this is exactly what you're looking for right? If it is then we can do it using closures and a global (bool) value for refresh token – KrishnaCA Dec 02 '16 at 17:34
  • I am already checking if the refresh token is expired or not before every single request. But as the my manager of network operations is async, sometimes two different request are made in a little time and they separately making a request to refresh the token. As a result of this, I get 400 from the second one. I am just looking for a solution to that. – Faruk Dec 02 '16 at 18:31

1 Answers1

1

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!")
            })
        })

    }
}
Faruk
  • 2,269
  • 31
  • 42