i have a code like this:
Task {
async let configsReq = self.interactor.getConfigs()
async let optionsReq = self.interactor.getOptions()
async let updateStateReq = self.interactor.getAppUpdateState()
async let contactsReq = self.interactor.getContactOptions()
var config: Config?
var options: AvailableOptions?
var updateState: UpdateType?
var contacts: ContactOptions?
do {
config = try await configsReq
} catch {
config = nil
}
do {
options = try await optionsReq
} catch {
options = nil
}
do {
updateState = try await updateStateReq
} catch {
updateState = nil
}
do {
contacts = try await contactsReq
} catch {
contacts = nil
}
self.goToNextPage()
}
in this case it does not matter for me that the requests get correct response or throws error. i don’t want to block user to get correct response.
And also I want to make sure that all my requests are answered (correct or error response) to take the user to the next page
how can i write these codes cleaner and better with new swift concurrency?
i tried like this (but i could not get match error to each related request):
Task {
async let configs = self.interactor.getConfigs()
async let options = self.interactor.getOptions()
async let updateState = self.interactor.getAppUpdateState()
async let contacts = self.interactor.getContactOptions()
do {
let array = try await [configs, options, updateState, contacts]
} catch {
print(error)
}
}
2
Answers
I would make a little helper that helps wrap the error into a
Result
:In case of errors, you even get the
Error
object for eachgetXXX
method, rather than just anil
. Of course, if you really just want anil
, you can write a helper that returns optionals instead.Then you could do:
The idea here is that you get a type that can contain both the response and error at the point of
async let
, rather than catching the error later.If I understand the question correctly, you want to:
If that is the pattern you are looking for, I might suggest using
Task
result
:Or, more concisely:
Where
goToNextPage
might be defined as:That way,
goToNextPage
can look at the.success
or.failure
for each, to retrieve either the value or error associated with each of the four requests.Needless to say, you also could have four properties for these four requests, and then
goToNextPage
could refer to those, rather than taking them as parameters to the method. It’s functionally the same thing, but you have to decide either local vars that are passed to the next method or update properties that are accessed by the next method.You asked:
Yes, we do not use
Result
very much, anymore, as that was historically a pattern for returning either value or error in traditional asynchronous patterns, and nowadays wetry
a series of tasks, catch thrown errors, but generally early exit once one of them fails.But if you really want to capture the success and failure for each of the four concurrent requests, then
Result
encapsulates that quite well.