Last active
June 25, 2022 12:25
-
-
Save krzyzanowskim/d31fb8ae46bd5ef272245f960fbcc26f to your computer and use it in GitHub Desktop.
Synchronously (well) wait for async Task value update https://twitter.com/krzyzanowskim/status/1523233140914876416
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// Wait for async operation to return value and call callback with the value | |
/// This class is intended to workaround/simplify async/await + actors isolation | |
/// https://twitter.com/krzyzanowskim/status/1523233140914876416 | |
private class AsyncWaiter<T> { | |
var didReceiveValue: Bool = false | |
let value: (T) -> Void | |
let operation: () async throws -> T | |
init(_ value: @escaping (T) -> Void, operation: @escaping () async throws -> T) { | |
self.value = value | |
self.operation = operation | |
} | |
func wait() { | |
Task.detached { | |
do { | |
self.value(try await self.operation()) | |
self.signal() | |
} catch { | |
self.signal() | |
throw error | |
} | |
} | |
while !didReceiveValue { | |
RunLoop.current.run(mode: .default, before: .distantFuture) | |
} | |
} | |
func signal() { | |
didReceiveValue = true | |
} | |
} | |
extension Task where Success == Void, Failure == CancellationError { | |
struct ValueError: LocalizedError { | |
var errorDescription: String? { | |
"Didn't receive asynchronous value." | |
} | |
} | |
public static func wait<T>(operation: @escaping () async throws -> T) throws -> T { | |
var v: T? = nil | |
AsyncWaiter({ | |
v = $0 | |
}, operation: operation).wait() | |
if let v = v { | |
return v | |
} else { | |
throw ValueError() | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
let result: [String] = try Task.wait { | |
try await foo.getValues() | |
} | |
print(result) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment