CoFuture
public class CoFuture<Value>
extension CoFuture: Hashable
extension CoFuture: Cancellable
Holder for a result that will be provided later.
CoFuture
and it’s subclass CoPromise
є імплементацією Future/Promise підходу.
Це дозволяє виконувати асинхронно роботу immediately повернувши CoFuture
, яке can
be observed to be notified when result will be available. For example:
extension URLSession {
typealias DataResponse = (data: Data, response: URLResponse)
func dataTaskFuture(for urlRequest: URLRequest) -> CoFuture<DataResponse> {
let promise = CoPromise<DataResponse>()
let task = dataTask(with: urlRequest) {
if let error = $2 {
promise.fail(error)
} else if let data = $0, let response = $1 {
promise.success((data, response))
} else {
promise.fail(URLError(.badServerResponse))
}
}
task.resume()
//cancel task if future will cancel
promise.whenCanceled(task.cancel)
return promise
}
}
За допомогою whenComplete()
ви можете додати callback або використати await()
в середині коротини для отримання результату. CoFuture
є повністю thread-safe.
Features
Best performance
Основною ціллю при створенні CoFuture
було досягнення найкращої швидкодії.
Було витрачено багато часу і перебрано багато варіантів для цього(для того щоб знайти найкращий).
Як результат CoFuture
є швидшим ніж аналогічні рішення:
- CoFuture - 0.083 c.
- Combine Future - 0.234 c. (2.8x slower)
- Найпопулярніша Swift Future/Promise library on GitHub - 0.521 c. (6.3x slower)
Тести для CoFuture
та Combine Future
ви можете знайти в файлі CoFuturePerformanceTests
.
Тест проводився на MacBook Pro (13-inch, 2017, Two Thunderbolt 3 ports) у release mode.
Build chains
За допомогою flatMap()
ви можете створювати chain of CoFuture
, that allows you to do
more asynchronous processing. Або ви можете використати map()
для синхронного трансформування.
В кінці ви можете використати whenSuccess()
or whenFailure()
для observing callback with the result or error.
//some future that will return URLRequest
let requestFuture: CoFuture<URLRequest>
requestFuture.flatMap { request in
URLSession.shared.dataTaskFuture(for: request)
}.flatMap { data, response in
CoFuture(on: .global) {
//do some work on global queue that return some result
}
}.map {
transformData($0)
}.whenComplete { result in
//result handler
}
Cancellable
За допомогою cancel()
ви можете завершити весь upstream chain of CoFutures.
Також ви можете handle cancelling і завершити пов’язані таски.
let future = URLSession.shared.dataTaskFuture(for: request)
future.whenCanceled {
//handle when canceled
}
//will also cancel URLSessionDataTask
future.cancel()
Awaitable
Ви можете використовувати await()
всередині Coroutine
для реалізації async/await патерну для отримання
результату. Вона дозволяє працювати з асинхронним кодом в синхронній манері без блокування потоку.
//execute coroutine on main thread
CoroutineDispatcher.main.execute {
//extension that returns CoFuture<URLSession.DataResponse>
let future = URLSession.shared.dataTaskFuture(for: request)
//await result that suspends coroutine and doesn't block the thread
let data = try future.await().data
//set the image on main thread
self.imageView.image = UIImage(data: data)
}
Combine ready
CoFuture
легко інтегрується з Combine, так за допомогою publisher()
ви можете створити Publisher
,
який transmit результат як тільки він буде готовий. Крім цього доPublisher
був доданий extension
subscribeCoFuture()
, який дає можливість subscribe CoFuture
, який отримає лише один результат.
Ви можете використовувати await()
для цього CoFuture
, щоб отримати результат для Publisher
всередині коротини.
CoroutineDispatcher.main.execute {
//returns Publishers.MapKeyPath<URLSession.DataTaskPublisher, Data>
let publisher = URLSession.shared.dataTaskPublisher(for: request).map(\.data)
//await data without blocking the thread
let data = try publisher.await()
//do some work with data
}
-
Initializes a future with result.
Declaration
Swift
@inlinable public convenience init(result: Result<Value, Error>)
Parameters
result
The result provided by this future.
-
Initializes a future with success value.
Declaration
Swift
@inlinable public convenience init(value: Value)
Parameters
value
The value provided by this future.
-
Initializes a future with error.
Declaration
Swift
@inlinable public convenience init(error: Error)
Parameters
error
The error provided by this future.
-
Returns completed result or nil if this future has not completed yet.
Declaration
Swift
public var result: Result<Value, Error>? { get }
-
Returns
true
when the current future is canceled.Declaration
Swift
@inlinable public var isCanceled: Bool { get }
-
Cancel цей та всі пов'язані future, засетавши всім результат з CoFutureError.canceled.
Declaration
Swift
public func cancel()
-
Adds an observer callback that is called when the
CoFuture
has any result.Declaration
Swift
public func whenComplete(_ callback: @escaping (Result<Value, Error>) -> Void)
Parameters
callback
The callback that is called when the
CoFuture
is fulfilled. -
Adds an observer callback that is called when the
CoFuture
has a success result.Declaration
Swift
@inlinable public func whenSuccess(_ callback: @escaping (Value) -> Void)
Parameters
callback
The callback that is called with the successful result of the
CoFuture
. -
Adds an observer callback is called when the
CoFuture
has a failure result.Declaration
Swift
@inlinable public func whenFailure(_ callback: @escaping (Error) -> Void)
Parameters
callback
The callback that is called with the failed result of the
CoFuture
. -
Adds an observer callback is called when the
CoFuture
was canceled.Declaration
Swift
@inlinable public func whenCanceled(_ callback: @escaping () -> Void)
Parameters
callback
The callback that is called when the
CoFuture
was canceled.
-
Undocumented
Declaration
Swift
public func await() throws -> Value
-
Declaration
Swift
@inlinable public static func == (lhs: CoFuture, rhs: CoFuture) -> Bool
-
Declaration
Swift
@inlinable public func hash(into hasher: inout Hasher)
-
Returns a publisher that emits result of this
CoFuture
.Declaration
Swift
public func publisher() -> AnyPublisher<Value, Error>