-
Notifications
You must be signed in to change notification settings - Fork 51
Add finally block feature #25
Comments
@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 |
@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 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! |
…detect mods to free blocks SwiftCoroutineDemo(39856,0x11266e600) malloc: nano zone abandoned due to inability to preallocate reserved vm space. DispatchQueue::scheduleTask() <OS_dispatch_queue_main: com.apple.main-thread> SharedCoroutineDispatcher::getFreeQueue(SwiftCoroutine.SharedCoroutineDispatcher) CoroutineContext::init(stackSize=196608, guardPage=true, SwiftCoroutine.CoroutineContext) returnEnv = 0x000060f0000042d0 stack = 0x000000010effb000 SharedCoroutineQueue::start(SwiftCoroutine.SharedCoroutineQueue) CoroutineContext::start(SwiftCoroutine.CoroutineContext) enter CoroutineContext::stackTop(SwiftCoroutine.CoroutineContext) 0x000000010f02b000 CoroutineContext::start(Optional(0x00006060000b8400)) block enter ==39856==WARNING: ASan is ignoring requested __asan_handle_no_return: stack type: default top: 0x7ff7b7045000; bottom 0x00010f028000; size: 0x7ff6a801d000 (140697357373440) False positive error reports may follow For details see google/sanitizers#189 CoroutineContext::start(SwiftCoroutine.CoroutineContext) leave DispatchQueue::scheduleTask() <OS_dispatch_queue_main: com.apple.main-thread> SharedCoroutineDispatcher::getFreeQueue(SwiftCoroutine.SharedCoroutineDispatcher) SharedCoroutineQueue::start(SwiftCoroutine.SharedCoroutineQueue) CoroutineContext::stackTop(SwiftCoroutine.CoroutineContext) 0x000000010f02b000 ================================================================= ==39856==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x00010f029ec1 at pc 0x00010949d77d bp 0x7ff7b7040e90 sp 0x7ff7b7040650 READ of size 4416 at 0x00010f029ec1 thread T0 #0 0x10949d77c in wrap_memcpy+0x16c (libclang_rt.asan_iossim_dynamic.dylib:x86_64+0x1977c) belozierov#1 0x109ef7f83 in SharedCoroutine.saveStack() SharedCoroutine.swift:79 belozierov#2 0x109eff514 in SharedCoroutineQueue.start(dispatcher:scheduler:task:) SharedCoroutineQueue.swift:39 belozierov#3 0x109efc229 in closure belozierov#1 in SharedCoroutineDispatcher.execute(on:task:) SharedCoroutineDispatcher.swift:27 belozierov#4 0x109ee7ed9 in OS_dispatch_queue.scheduleTask(_:) CoroutineScheduler+DispatchQueue.swift:16 belozierov#5 0x109ee88ad in protocol witness for CoroutineScheduler.scheduleTask(_:) in conformance OS_dispatch_queue <compiler-generated> belozierov#6 0x109efbf48 in SharedCoroutineDispatcher.execute(on:task:) SharedCoroutineDispatcher.swift:26 belozierov#7 0x109ee3616 in CoroutineScheduler._startCoroutine(_:) CoroutineScheduler.swift:51 belozierov#8 0x109ee3c78 in CoroutineScheduler.startCoroutine(in:task:) CoroutineScheduler.swift:69 belozierov#9 0x108ebe2ed in AppDelegate.test() AppDelegate.swift:43 belozierov#10 0x108ebdd77 in AppDelegate.application(_:didFinishLaunchingWithOptions:) AppDelegate.swift:18 belozierov#11 0x108ebe4b7 in @objc AppDelegate.application(_:didFinishLaunchingWithOptions:) <compiler-generated> belozierov#12 0x7fff2509a592 in -[UIApplication _handleDelegateCallbacksWithOptions:isSuspended:restoreState:]+0xd5 (UIKitCore:x86_64+0xcd7592) belozierov#13 0x7fff2509c283 in -[UIApplication _callInitializationDelegatesWithActions:forCanvas:payload:fromOriginatingProcess:]+0x101f (UIKitCore:x86_64+0xcd9283) belozierov#14 0x7fff250a1c23 in -[UIApplication _runWithMainScene:transitionContext:completion:]+0x4a5 (UIKitCore:x86_64+0xcdec23) belozierov#15 0x7fff246124a2 in -[_UISceneLifecycleMultiplexer completeApplicationLaunchWithFBSScene:transitionContext:]+0xb2 (UIKitCore:x86_64+0x24f4a2) belozierov#16 0x7fff2509e2ac in -[UIApplication _compellApplicationLaunchToCompleteUnconditionally]+0x3a (UIKitCore:x86_64+0xcdb2ac) belozierov#17 0x7fff2509e64b in -[UIApplication _run]+0x391 (UIKitCore:x86_64+0xcdb64b) belozierov#18 0x7fff250a32b4 in UIApplicationMain+0x64 (UIKitCore:x86_64+0xce02b4) belozierov#19 0x7fff59d55cc1 in UIApplicationMain(_:_:_:_:)+0x61 (libswiftUIKit.dylib:x86_64+0x21cc1) belozierov#20 0x108ebf357 in static UIApplicationDelegate.main() <compiler-generated> belozierov#21 0x108ebf2a0 in static AppDelegate.$main() AppDelegate.swift:11 belozierov#22 0x108ebfc77 in main <compiler-generated> belozierov#23 0x1090f8f20 in start_sim+0x9 (dyld_sim:x86_64+0x1f20) belozierov#24 0x1125f352d (<unknown module>) 0x00010f029ec1 is located 192193 bytes inside of 200704-byte region [0x00010effb000,0x00010f02c000) allocated by thread T0 here: #0 0x1094c7bb3 in wrap_posix_memalign+0xb3 (libclang_rt.asan_iossim_dynamic.dylib:x86_64+0x43bb3) belozierov#1 0x7fff30c9e62c in swift_slowAlloc+0x4c (libswiftCore.dylib:x86_64+0x30762c) belozierov#2 0x109ede243 in CoroutineContext.init(stackSize:guardPage:) CoroutineContext.swift:32 belozierov#3 0x109eddc1f in CoroutineContext.__allocating_init(stackSize:guardPage:) CoroutineContext.swift belozierov#4 0x109efe985 in SharedCoroutineQueue.init(stackSize:) SharedCoroutineQueue.swift:28 belozierov#5 0x109efe5c3 in SharedCoroutineQueue.__allocating_init(stackSize:) SharedCoroutineQueue.swift belozierov#6 0x109efcb3d in SharedCoroutineDispatcher.getFreeQueue() SharedCoroutineDispatcher.swift:38 belozierov#7 0x109efc20d in closure belozierov#1 in SharedCoroutineDispatcher.execute(on:task:) SharedCoroutineDispatcher.swift:27 belozierov#8 0x109ee7ed9 in OS_dispatch_queue.scheduleTask(_:) CoroutineScheduler+DispatchQueue.swift:16 belozierov#9 0x109ee88ad in protocol witness for CoroutineScheduler.scheduleTask(_:) in conformance OS_dispatch_queue <compiler-generated> belozierov#10 0x109efbf48 in SharedCoroutineDispatcher.execute(on:task:) SharedCoroutineDispatcher.swift:26 belozierov#11 0x109ee3616 in CoroutineScheduler._startCoroutine(_:) CoroutineScheduler.swift:51 belozierov#12 0x109ee3c78 in CoroutineScheduler.startCoroutine(in:task:) CoroutineScheduler.swift:69 belozierov#13 0x108ebe2ed in AppDelegate.test() AppDelegate.swift:43 belozierov#14 0x108ebdd77 in AppDelegate.application(_:didFinishLaunchingWithOptions:) AppDelegate.swift:18 belozierov#15 0x108ebe4b7 in @objc AppDelegate.application(_:didFinishLaunchingWithOptions:) <compiler-generated> belozierov#16 0x7fff2509a592 in -[UIApplication _handleDelegateCallbacksWithOptions:isSuspended:restoreState:]+0xd5 (UIKitCore:x86_64+0xcd7592) belozierov#17 0x7fff2509c283 in -[UIApplication _callInitializationDelegatesWithActions:forCanvas:payload:fromOriginatingProcess:]+0x101f (UIKitCore:x86_64+0xcd9283) belozierov#18 0x7fff250a1c23 in -[UIApplication _runWithMainScene:transitionContext:completion:]+0x4a5 (UIKitCore:x86_64+0xcdec23) belozierov#19 0x7fff246124a2 in -[_UISceneLifecycleMultiplexer completeApplicationLaunchWithFBSScene:transitionContext:]+0xb2 (UIKitCore:x86_64+0x24f4a2) belozierov#20 0x7fff2509e2ac in -[UIApplication _compellApplicationLaunchToCompleteUnconditionally]+0x3a (UIKitCore:x86_64+0xcdb2ac) belozierov#21 0x7fff2509e64b in -[UIApplication _run]+0x391 (UIKitCore:x86_64+0xcdb64b) belozierov#22 0x7fff250a32b4 in UIApplicationMain+0x64 (UIKitCore:x86_64+0xce02b4) belozierov#23 0x7fff59d55cc1 in UIApplicationMain(_:_:_:_:)+0x61 (libswiftUIKit.dylib:x86_64+0x21cc1) belozierov#24 0x108ebf357 in static UIApplicationDelegate.main() <compiler-generated> belozierov#25 0x108ebf2a0 in static AppDelegate.$main() AppDelegate.swift:11 belozierov#26 0x108ebfc77 in main <compiler-generated> belozierov#27 0x1090f8f20 in start_sim+0x9 (dyld_sim:x86_64+0x1f20) belozierov#28 0x1125f352d (<unknown module>) SUMMARY: AddressSanitizer: stack-buffer-overflow (libclang_rt.asan_iossim_dynamic.dylib:x86_64+0x1977c) in wrap_memcpy+0x16c Shadow bytes around the buggy address: 0x0001344ad380: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x0001344ad390: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x0001344ad3a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x0001344ad3b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x0001344ad3c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 =>0x0001344ad3d0: 00 00 00 00 f1 f1 f1 f1[01]f3 f3 f3 00 00 00 00 0x0001344ad3e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x0001344ad3f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x0001344ad400: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x0001344ad410: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x0001344ad420: 00 00 00 00 00 00 00 00 00 00 00 00 ca ca ca ca Shadow byte legend (one shadow byte represents 8 application bytes): Addressable: 00 Partially addressable: 01 02 03 04 05 06 07 Heap left redzone: fa Freed heap region: fd Stack left redzone: f1 Stack mid redzone: f2 Stack right redzone: f3 Stack after return: f5 Stack use after scope: f8 Global redzone: f9 Global init order: f6 Poisoned by user: f7 Container overflow: fc Array cookie: ac Intra object redzone: bb ASan internal: fe Left alloca redzone: ca Right alloca redzone: cb ==39856==ABORTING AddressSanitizer report breakpoint hit. Use 'thread info -s' to get extended information about the report. (lldb)
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
The text was updated successfully, but these errors were encountered: