swiftasynchronousasync-awaitcompletionhandler

Swift - Async/Await not stopping to let task finish


I'm writing a simple program designed to talk to a server, get some information, and display it. However, I'm running into issues with the async code, mainly that the code isn't stopping to allow the server to respond before continuing.

I know I have to be doing something wrong but have no idea what, any help is appreciated.

override func viewDidLoad() {
    super.viewDidLoad()
    Task{
        let accessToken = await getToken()
    }
    print("Done")
}

private func getToken() async -> String{
    let url = URL(string: "https://api.petfinder.com/v2/oauth2/token")
    let payload = "grant_type=client_credentials&client_id=GUQj1MdQN3QunoxXz4vdd0DHPlcJC6yuqCLCEXavriJ4W6wTYV&client_secret=7whgSG3ZX6m9Cwfr2vEakOH90fSn3g0isIlae0CC".data(using: .utf8)
    var request = URLRequest(url: url!)
    request.httpMethod = "POST"
    request.httpBody = payload

    do{
        let (data,_) = try await URLSession.shared.data(for: request)
        let APItoken: token = try! JSONDecoder().decode(token.self, from: data)
        return APItoken.access_token
    }
    catch{
        return ""
    }
}

Solution

  • If I understood the problem, you see "Done" being printed before the getToken() method is completed, right?

    The problem is that print("Done") is outside of the Task.

    When you call Task, it starts running what's in the closure and it immediately resumes after the closure, while your task is running in parallel, without blocking the main thread.

    Place your print() inside the Task closure, right after the getToken() method, and you'll see that it'll be "Done" after you complete your POST request.

        Task{
            let accessToken = await getToken()
            print("Done")
        }