Skip to content

Instantly share code, notes, and snippets.

@kean
Last active November 24, 2018 22:47
Show Gist options
  • Save kean/24a3d0c2538647b33006b344ebc283a7 to your computer and use it in GitHub Desktop.
Save kean/24a3d0c2538647b33006b344ebc283a7 to your computer and use it in GitHub Desktop.
Fake (blocking) Async/Await for https://github.com/kean/FutureX
class AsyncAwaitTests: XCTestCase {
func testAsyncAwait() {
XCTAssertEqual(fakeAsyncAwait().wait().value, 3)
}
}
func fakeAsyncAwait() -> Future<Int, Error> {
return Future.async {
// Add delay to demonstrate that `await` for `Future<_, Never>` don't
// require `try`.
Future.after(seconds: 1).await()
// Performing async tasks in a synchronous manner.
let data = try loadData().await()
let string = try decodeData(data).await()
return string.count
}
}
// WARNING: this won't compile, it's based on the https://gist.github.com/lattner/429b9070918248274f25b714dcfc7619
func realAsyncAwait() async throws -> Int {
// This is a contribed example.
await Future.after(seconds: 1)
let string = try await decodeData(loadData())
return string.count
}
func loadData() -> Future<Data, Error> {
let promise = Promise<Data, Error>()
let data = "123".data(using: .utf8)!
DispatchQueue.global().asyncAfter(deadline: .now() + .seconds(1)) {
promise.succeed(value: data)
}
return promise.future
}
func decodeData(_ data: Data) -> Future<String, Error> {
let promise = Promise<String, Error>()
DispatchQueue.global().asyncAfter(deadline: .now() + .seconds(1)) {
// Some long async task here
let string = String(data: data, encoding: .utf8)!
// Using force unwrap just for a demo purposes, production code
// must have error handling!
promise.succeed(value: string)
}
return promise.future
}
// WARNING: This is just a demo. Real async/await is not blocking
// and requires compiler suppport. In this demo async/await is
// blocking and goes down to the kernel to block threads.
// MARK: - Async/Await
extension Future where Error == Swift.Error {
public static func async(_ closure: @escaping () throws -> Value) -> Future {
let promise = Promise()
asyncQueue.async {
do {
let value = try closure()
promise.succeed(value: value)
} catch {
promise.fail(error: error)
}
}
return promise.future
}
public func await() throws -> Value {
switch wait() {
case let .success(value): return value
case let .failure(error): throw error
}
}
}
extension Future where Error == Never {
public func await() -> Value {
return wait().value!
}
}
private let asyncQueue = DispatchQueue(label: "com.github.kean.futurex.async-queue", attributes: .concurrent)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment