0

How to pause another async call if one of them catch a condition that need to be done first before continuing the other calls? From the code below (simplified), when makeRequest got 401, then it should call refreshSession and pause other calls until this one is finished.

let refreshSessionDispatchQueue = DispatchQueue(label: "refreshSession")
var refreshSessionJobQueue: [APIRequest] = []

// This function will be called by each of APIs that got 401 error code
private func refreshSession(errorCode: String? = nil, request: APIRequest) {
    refreshSessionDispatchQueue.async {
        self.refreshSessionJobQueue.append(request)
    }

    // The idea is, after all job appended to the jobQueue, let says after 1', it will call another function to execute another job
    DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 1) {
        self.executeRefreshSessionJobQueue()
    }
}

// This is to execute refreshSession, and if it's succeed, all job on the jobQueue will be re-executed
private func executeRefreshSessionJobQueue() {
    DispatchQueue.main.async {
        let readyToRefreshSessionJobQueue = self.refreshSessionJobQueue
        
        if self.refreshSessionJobQueue.count > 0 {
            self.refreshSessionJobQueue = []

            self.refreshSession { [weak self] succeed in
                if succeed {
                    for job in readyToRefreshSessionJobQueue {
                        self?.makeRequest(baseURL: job.baseURL, endpoint: job.endpoint, method: job.method, encoding: job.encoding, headers: job.headers, params: job.params, customBody: job.customBody, completion: job.completion)
                    }
                    self?.refreshSessionJobQueue = []
                } else {
                    // And if it's failed, all the job should be removed and redirect the page to the login page
                    self?.refreshSessionJobQueue = []
                    ErrorHandler.relogin()
                }
            }
            
        }
    }
}
mrjimoy_05
  • 3,452
  • 9
  • 58
  • 95
  • 2
    It kind of looks like in this scenario you don't want to execute them concurrently but rather in sequence (wait for the 1st one to complete and only then do the next request and so on). The way you call them in your example would start them all "at the same time" and before the backend call returns you're already past your comment where you want to wait – Goergisn Nov 10 '20 at 09:04
  • In real life all of your requests return 401 and there is no a reason to pause any of them so I'm greed with @Goergisn you should make requests stack/sequence and run your requests one by one and recreate your session if it's needed. For concurrent requests you can create new session on first fail but then you should to recreate all your requests once again. – iUrii Nov 16 '20 at 19:13

1 Answers1

0

If you need to retry the API when getting 401, you can try using RequestRetrier from Alamofire’s RequestInterceptor. It basically retries a request that encountered an error such as 401 in your case.

Full example of implementation can be found here. Hope it helps, cheers!

Anthonius
  • 290
  • 1
  • 9