When using a Future I'm not able to receive the cancel event.
Future<String, Never> { promise in
promise(.success("Hello Stackoverflow"))
}
.eraseToAnyPublisher()
.handleEvents(receiveCancel: {
print("Cancel event received here")
})
.sink(receiveValue: { value in
print(value)
})
.store(in: &disposeBag)
disposeBag.map { $0.cancel() }
Interestingly using a subject it's working and I'm getting the event.
let subject = PassthroughSubject<String, Never>()
subject.send("Hello Stackoverflow")
subject.eraseToAnyPublisher()
.handleEvents(receiveCancel: {
print("Cancel event received here")
})
.sink(receiveValue: { value in
print(value)
})
.store(in: &disposeBag)
disposeBag.map { $0.cancel() }
So why is Combine behaving that way and how I can resolve this?
A Future perfoms its work once as soon as it's created, and it completes after fulfilling its promise. So in your code, by the time $0.cancel is called the Future has already completed.
A PassthroughSubject runs for a longer period of time because it can publish an infinite number of values, that's why you can capture the cancel.
If you delay the fulfilment of the promise you can capture the cancel event like you'd want:
var disposeBag = Set<AnyCancellable>()
Future<String, Never> { promise in
DispatchQueue.global().asyncAfter(deadline: .now() + 1) {
promise(.success("Hello Stackoverflow"))
}
}
.eraseToAnyPublisher()
.handleEvents(receiveCancel: {
print("Cancel event received here")
})
.sink(receiveValue: { value in
print(value)
})
.store(in: &disposeBag)
disposeBag.map { $0.cancel() }
Note that the execution of the closure that's passed to the future isn't cancelled because it's already running. The subscription is just cancelled and you won't receive the result.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With