Closed mickaelhero closed 4 years ago
@mickaelhero Hi, I like your approach but the main idea of this framework is to reduce the use of chains and other reactive programming approaches (although the framework includes everything you need to build chains, but it's like extra features).
The native Swift version should look like this:
DispatchQueue.main.startCoroutine {
isLoading = true
do {
try self.service.getAll().await()
} catch {
Log.s("Error 1 occurred: \(error.localizedDescription)")
}
do {
try self.service.getAll().await()
} catch {
Log.s("Error 2 occurred: \(error.localizedDescription)")
}
isLoading = false
}
You can do it a little better with extensions:
extension CoFuture where Value == Void {
func await(catchBlock: (Error) -> Void) {
do { try await() } catch { catchBlock(error) }
}
}
DispatchQueue.main.startCoroutine {
var isLoading = true
self.service.getAll().await { error in
Log.s("Error 1 occurred: \(error.localizedDescription)")
}
self.service.getAll().await { error in
Log.s("Error 2 occurred: \(error.localizedDescription)")
}
isLoading = false
}
You can also create an extension for Sequence where Element: CoFuture<Void>
, etc.
@mickaelhero You can also do so, it all depends on what errors you want to handle and how:
DispatchQueue.main.startCoroutine {
isLoading = true
defer { isLoading = false }
do {
try self.service.getAll().await()
try self.service.getAll().await()
try self.service.getAll().await()
} catch {
Log.s("Error occurred: \(error.localizedDescription)")
}
// Or you can put `isLoading = false` here if you don’t like `defer`
}
@mickaelhero Also, you can use the available methods to build chains:
DispatchQueue.main.coroutineFuture {
try self.service.getAll().await()
try self.service.getAll().await()
try self.service.getAll().await()
}.recover { error in
Log.s("Error occurred: \(error.localizedDescription)")
}.whenComplete {
isLoading = false
}
But I'm not a fan of chains for a number of reasons. The idea of the async/await pattern is to reduce or avoid their use. The do-catch
version is more readable, native and doesn't require additional allocation of CoFuture
or any other objects.
Also, as an option you can write, quite succinctly:
DispatchQueue.main.coroutineFuture {
isLoading = true
defer { isLoading = false }
try self.service.getAll().await()
try self.service.getAll().await()
try self.service.getAll().await()
}.whenFailure { error in
Log.s("Error occurred: \(error.localizedDescription)")
}
Thanks for your answer helped me a lot :). The best async/await lib!
Hi,
I developed a feature that I found missing.
The problem is that I want to continue the execution of a coroutine block even if there is an error, for example a loader must disappear after the request whether there is an error or not.
With current framework:
With this version as soon as there is an error we do not continue the block we go into the catch block. But the problem is that
isLoading = false
is written twiceI know I can also do this which will not stop the block but it is not what I reach, if there is an error I want the block to be stopped
So my solution is as follows, I wrap the coroutine block to make it clearer, Async / Await. And I added 2 blocks to catch the error, and a finally block which will be executed even if we get an error.
I already wrote this wrapper, if you are interested in integrating it into the framework I can make a pull request. This way will not replace the old way, it will just be a new possibility way