I recently changed my http request method to async/await
in swift.
func httpRequest(requestType:HTTPRequestType, parameter:Parameter = Parameter()) async throws -> Data {
// do some preparation depending on requestType and parameter,
// e.G. find the right URL, setting http-method to POST / GET / DELETE / PUT and generate headers and body
let (data, response):(Data, URLResponse) = try await {
do {
return try await self.httpSession.data(for: request)
} catch {
throw HTTPRequestError.noNetwork // check for network errors
}
}()
// Handle Response and return Data-Object or throw, for example if login is not correct
}
It all works fine, as long as I call ONE function - for example
func login(username:String, password:String) async throws {
let dataCredentials = try await httpRequest(requestType: .login)
let credentials = try await decodeData(dataCredentials)
// Request own userdata
let dataUserdata = try await httpRequest(requestType: .requestOwnUserData)
let userdata = try await decodeData(dataUserData)
// Request users notifications
let dataNotifications = try await httpRequest(requestType: .requestUserNotifications)
let notifications = try await decodeData(dataNotifications)
// and some more actions
}
This so far works very well - I do get a problem though as soon as the user presses another button. This - obviously - creates a new task that does not "queue" in the login, but creates a separate thread that is being worked on. It might happen though that there are dependencies - so I want to make sure that all task are being send to the server in that order that my user performed them. For now, I call my requests like this:
Button(action: {
Task {
do {
try await login(username: username, password: password)
} catch let error {
// handle error
}
}
}, label: {
Text("Login")
})
In a perfect world I could also count how many tasks are left there, but that's not essential. Though - in this case I could/would also split up my login()
into severals tasks.