Created
October 28, 2019 09:31
-
-
Save piv199/925e4c046f2758bf29b6e77a1341ad88 to your computer and use it in GitHub Desktop.
Example of cancellable custom publisher
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
extension Service { | |
private func request(_ request: RequestConvertible) -> Request { | |
self.resource(request.path) | |
.request(request.method) { urlRequest in | |
request.headers?.forEach { urlRequest.addValue($0.value, forHTTPHeaderField: $0.key) } | |
request.mutation?(&urlRequest) | |
} | |
} | |
struct RequestPublisher: Publisher { | |
typealias Output = Void | |
typealias Failure = Error | |
private let service: Service | |
private let requestModel: RequestConvertible | |
init(service: Service, request: RequestConvertible) { | |
self.service = service | |
self.requestModel = request | |
} | |
func receive<S>(subscriber: S) where S: Subscriber, Failure == S.Failure, Output == S.Input { | |
let request = service.request(requestModel) | |
.onSuccess { response in | |
//notify about success | |
_ = subscriber.receive() | |
subscriber.receive(completion: .finished) | |
} | |
.onFailure { error in | |
//notify about failure | |
subscriber.receive(completion: .failure(error)) | |
} | |
.start() | |
subscriber.observe(cancel: { request.cancel() }) | |
} | |
} | |
func publisher(request: RequestConvertible) -> RequestPublisher { | |
return .init(service: self, request: request) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
extension Subscriptions { | |
struct Cancellable: Subscription { | |
let combineIdentifier = CombineIdentifier() | |
private let cancelBlock: () -> Void | |
private let requestDemand: ((Subscribers.Demand) -> Void)? | |
init(cancel: @escaping () -> Void, requestDemand: ((Subscribers.Demand) -> Void)? = nil) { | |
cancelBlock = cancel | |
self.requestDemand = requestDemand | |
} | |
func cancel() { cancelBlock() } | |
func request(_ demand: Subscribers.Demand) { requestDemand?(demand) } | |
} | |
} | |
extension Subscriber { | |
func observe(cancel: (() -> Void)? = nil, demand: ((Subscribers.Demand) -> Void)? = nil) { | |
self.receive(subscription: Subscriptions.Cancellable(cancel: { cancel?() }, request: { demand?($0) })) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment