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.

result

  • Returns completed result or nil if this future has not completed yet.

    Declaration

    Swift

    public var result: Result<Value, Error>? { get }

cancel

  • 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()

whenComplete

  • 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.

await

  • Undocumented

    Declaration

    Swift

    public func await() throws -> Value

hashable

  • Declaration

    Swift

    @inlinable
    public static func == (lhs: CoFuture, rhs: CoFuture) -> Bool
  • Declaration

    Swift

    @inlinable
    public func hash(into hasher: inout Hasher)

publisher

  • Returns a publisher that emits result of this CoFuture.

    Declaration

    Swift

    public func publisher() -> AnyPublisher<Value, Error>