Home > Blockchain >  How to async await empty response using Alamofire
How to async await empty response using Alamofire

Time:06-22

I have an API where I PUT stuff to. I need to make sure to wait until I get an http 200 response from the server, but I don't know how to await that using Alamofire because my response itself if empty. So it's just an http 200 with no content.

I only can find async functions that e.g. serialize a String or Data or a Decodable, but they don't work if my response is empty.

Is there a way to await something like that in Alamofire?

CodePudding user response:

If Alamofire does not provide a method for your purpose, then you will have wrap the old Alamofire methods that uses closures as below:

    func myRequest() async throws {
        try await withUnsafeThrowingContinuation { continuation in
            myAlamofireRequest {
                continuation.resume()
            }
        }
    }

CodePudding user response:

I know that your question is about async/await from Alamofire, but is good to know that the http status codes 204 and 205 are exactly for this. Which means that if you have access to the server code you could send the empty responses with the http status code 204 and 205 instead of 200 and then Alamofire would not generate any errors. But assuming you don't have access to the server code and you need to parse an empty response as correct then you could use the following code:

func testRequestWithAlamofire() {
        let dataResponseSerializer = DataResponseSerializer(emptyResponseCodes: [200, 204, 205]) // Default is [204, 205] so add 200 too :P
        
        AF.request("http://www.mocky.io/v2/5aa696133100001335e716e0", method: .put).response(responseSerializer: dataResponseSerializer) { response in
            switch response.result {
                case .failure(let error):
                    print(error)
                case .success(let value):
                    print(value)
            }
        }
    }

And for a real and complete example of how async/await from Alamofire or any other async context look this code:

// This function get report from API and save to a local JSON to be readed by the app
    func updateReport() {
        Task {
            
            guard let session = self.sessionRepository.getSession(WithUser: Defaults.lastLoggedUsername!) else { return }
            guard let company = session.profile?.companies.first else { return }
            self.apiManager.configure(WithToken: session.accessToken)
            
            do {
                let dateA = Date().dateAtStartOf(.year)
                //let dateB = Date().dateAtEndOf(.month)
                let dateB = Date() // Just now
                
                let report = try await self.apiManager.report(CompanyId: company._id, DateA: dateA, DateB: dateB, ChartPeriodicity: .month)
                
                self.currentReport = report
                
                // Save data to disk to be read later
                self.reportManager.saveReportToDisk(report: report!, withProfileId: session.profile!._id)
            } catch {
                print("Error getting report: \(error)")
            }
        }
    }

// Get personal report from a given date range
    func report(CompanyId companyId: String, DateA dateA: Date, DateB dateB: Date, ChartPeriodicity chartPeriodicity: ChartPeriodicity) async throws -> CDReport? {
        try await withCheckedThrowingContinuation { continuation in
            self.contappApi.request(.report(companyId: companyId, dateA: dateA, dateB: dateB, chartPeriodicity: chartPeriodicity)) { result in
                switch result {
                case let .success(response):
                    // Check status code
                    guard response.statusCode == 200 else {
                        continuation.resume(throwing: ContappNetworkError.unexpected(code: response.statusCode))
                        return
                    }
                    
                    // Decode data
                    do {
                        //let report = try JSONDecoder().decode(CDReport.self, from: response.data)
                        let report = try CDReport(data: response.data)
                        continuation.resume(returning: report)
                    } catch {
                        continuation.resume(throwing: ContappNetworkError.cantDecodeDataFromNetwork)
                    }
                    
                case .failure(_):
                    continuation.resume(throwing: ContappNetworkError.networkError)
                }
            }
        }
    }
  • Related