# `AsyncOperation` - generic сабкласс Operation Позволяет запускать: - асинхронный код внутри операции - собирать цепочки из операций - подписываться на результат выполнения ## Базовые операции "Из коробки", на данный момент, доступен всего один сабкласс асинхронной операции, потому что больше обычно и не нужно. Но можно наследоваться и создавать собственные сабклассы при необходимости. ### `ClosureAsyncOperation` Операция принимающая некий closure, который по окончании своей работы вызовет completion, переданный ему параметром ```swift import Foundation import TIFoundationUtils let intResultOperation = ClosureAsyncOperation { completion in DispatchQueue.global().asyncAfter(deadline: .now() + .seconds(3)) { completion(.success(1)) } return Cancellables.nonCancellable() } ``` ## Базовые операторы На данный момент реализовано четыре оператора: - `map(mapOutput:mapFailure:)` - конвертирует ResultType в новый NewResultType и ErrorType в новый NewErrorType - `observe(onSuccess:onFailure)` - просто вызывает переданные callback'и при получении результата или ошибки - `flatMap(_:)` - подписывается на результат выполнения нового AsyncOperation полученного из closure - `flatMapError(_:)` - подписывается на результат выполнения нового AsyncOperation полученного из closure ### Пример запуска асинхронных операци с применением операторов в последовательной очереди и вывод результатов ```swift let operationQueue = OperationQueue() operationQueue.maxConcurrentOperationCount = 1 ClosureAsyncOperation { completion in DispatchQueue.global().asyncAfter(deadline: .now() + .seconds(3)) { completion(.success(1)) } return Cancellables.nonCancellable() } .map { $0 * 2 } .observe(onSuccess: { result in debugPrint("Async operation one has finished with \(result)") }) .add(to: operationQueue) ClosureAsyncOperation { completion in DispatchQueue.global().asyncAfter(deadline: .now() + .seconds(1)) { completion(.success("Success")) } return Cancellables.nonCancellable() } .observe(onSuccess: { result in debugPrint("Async operation two has finished with \(result)") }) .add(to: operationQueue) ``` В консоли будет выведено: ``` "Async operation one has finished with 2" "Async operation two has finished with Success" ``` ### Пример использования оператора flatMap у AsyncOperaton ```swift import TISwiftUtils extension StorageKey { static var loyaltyCardNumber: StorageKey { .init(rawValue: "loyaltyCardNumber") } } struct CardService { enum Failure: Error { case noCardFound case cardFetchError } private let operationQueue = OperationQueue() private let asyncStorage = StringValueDefaultsStorage(defaults: .standard, storageKey: .loyaltyCardNumber) .async(on: .global()) func requestCardTitle(cardNumber: String) -> AsyncOperation { .just(success: "Supreme card") // .just(failure: .cardFetchError) } func getSavedCardTitle(completion: @escaping UIParameterClosure>) -> Cancellable { ClosureAsyncOperation { completion in asyncStorage.getValue { completion($0.mapError { _ in .noCardFound }) } } .flatMap { requestCardTitle(cardNumber: $0) } .observe(onResult: completion) .add(to: operationQueue) } } let cardService = CardService() cardService.getSavedCardTitle { result in debugPrint(result) } Nef.Playground.needsIndefiniteExecution(true) ```