Classes

The following classes are available globally.

  • 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
    }
    
    See more

    Declaration

    Swift

    public class CoFuture<Value>
    extension CoFuture: Hashable
    extension CoFuture: Cancellable
  • A promise to provide a result later.

    CoPromise is subclass of CoFuture, що має методи, які дозволяють fulfill it. Це дозволяє інкапсулювати result provider. Ви можете тільки один раз засетати результат в CoPromise, всі інші рази будуть ігноруватись.

    See more

    Declaration

    Swift

    public final class CoPromise<Value> : CoFuture<Value>