Hi,
There are roughly two ways to design a function in Swift:
- asynchronous (using a completion)
- synchronous (using a return value)
Synchronous functions can also run on a background thread to not block UI and still return a value (to avoid endless completion handlers stacked in one another).
Trying to avoid:
doA({
doB({
doC({
// ...
})
})
})
Getting to this:
DispatchQueue.global(qos: .background) {
let a = doA()
let b = doB()
let c = doC()
}
Looks much better right? Only visually. What if doC() does not need a
nor b
?
It waits for the executions to finish before executing. Which is bad. In JS this is called an await/async hell.
One could argue why not do both:
doSomething()
doNotWait({
})
doNoWaitEither({
})
doSomethingThatWaits()
However then you always need to use completion handlers to not block and potentially sync if you want to block the execution.
And if you suddenly want to wait for doNotWait
you need to wrap it in DispatchGroup
or DispatchSemaphore
to handle synchronous execution - potentially in multiple parts of your program.
And as soon as you make it synchronous, you need to accept that it blocks other functions that are absolutely not related.
In Javascript there is Promise.all([...]), which waits on all functions in the array to return, without blocking one or the other from executing.
I was wondering if this can be implemented in Swift.
Options would be:
- Threads
- Completion Handlers and a DispatchGroup / DispatchSemaphore
- Future Extension (Combine Framework) [iOS 13 only ]
Any other idea how you would approach this issue?
Here is my use case:
I defined my own API for my server so all requests are synchronous, which means each API function returns the data from the API and then I have something like this:
// on a background queue
API.setVersion(AppSettings.appVersion)
API.getToken(for: user)
API.getSettings()
And neither of those functions needs to wait on the others to complete.
Any help / ideas appreciated!