Skip to content

Instantly share code, notes, and snippets.

@sergdort
Last active June 12, 2021 11:51
Show Gist options
  • Save sergdort/d5d3cc28cc9df889ab6b1410d16581ad to your computer and use it in GitHub Desktop.
Save sergdort/d5d3cc28cc9df889ab6b1410d16581ad to your computer and use it in GitHub Desktop.
Bridge between async await and Publisher.
@available(iOS 15.0, *)
struct TaskPublisher<Output>: Publisher{
typealias Failure = Never
let work: () async -> Output
init(work: @escaping () async -> Output) {
self.work = work
}
func receive<S>(subscriber: S) where S : Subscriber, Self.Failure == S.Failure, Self.Output == S.Input {
let subscription = TaskSubscription(work: work, subscriber: subscriber)
subscriber.receive(subscription: subscription)
subscription.start()
}
final class TaskSubscription<Output, Downstream: Subscriber>: Combine.Subscription where Downstream.Input == Output, Downstream.Failure == Never {
private var handle: Task.Handle<Output, Never>?
private let work: () async -> Output
private let subscriber: Downstream
init(work: @escaping () async -> Output, subscriber: Downstream) {
self.work = work
self.subscriber = subscriber
}
func start() {
self.handle = async { [subscriber, work] in
let result = await work()
_ = subscriber.receive(result)
subscriber.receive(completion: .finished)
return result
}
}
func request(_ demand: Subscribers.Demand) {}
func cancel() {
handle?.cancel()
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment