I was addicted to using Combine because of lack of study, so I will leave it as a memorandum.
In the Future type variable returned by the function
func handleEvents(
receiveSubscription: ((Subscription) -> Void)? = nil,
receiveOutput: ((Output) -> Void)? = nil,
receiveCompletion: ((Subscribers.Completion<Failure>) -> Void)? = nil,
receiveCancel: (() -> Void)? = nil,
receiveRequest: ((Subscribers.Demand) -> Void)? = nil
) -> Publishers.HandleEvents<Future<Output, Failure>>
I want to call to do something inside the closure, but the closure doesn't run.
https://developer.apple.com/documentation/combine/future/handleevents(receivesubscription:receiveoutput:receivecompletion:receivecancel:receiverequest:)
func sink(
receiveCompletion: @escaping ((Subscribers.Completion<Failure>) -> Void),
receiveValue: @escaping ((Output) -> Void)
) -> AnyCancellable
You need to connect the subscribers by calling the above sink.
https://developer.apple.com/documentation/combine/future/sink(receivecompletion:receivevalue:)
Initially, I implemented the following code and thought that the closure set by hanleEvents would be called when promise (.success (())) was executed. But not called.
//Run on Playground
import Combine
import Foundation
struct APIError: Error {
var description: String
}
func delay() -> Future<Void, Error> {
return Future<Void, Error>{ promise in
print("It will be executed")
Thread.sleep(forTimeInterval: 2.0)
promise(.success(()))
return
}
}
func executionDelay() -> AnyPublisher<Void, Error>{
print("I will do it")
return delay()
.handleEvents(receiveSubscription: {_ in
print("Subscription")
}, receiveOutput: { _ in
print("Output")
}, receiveCompletion: { _ in
print("Completion")
}, receiveCancel: {
print("Cancel")
}, receiveRequest: {_ in
print("Request")
})
.eraseToAnyPublisher()
}
//Execute processing
executionDelay()
If you read the handleEvents reference, it says "Performs the specified closures when publisher events occur." And closures are executed when publisher events occur. However, when I thought about it, I noticed that I was not connected to the subscriber. You need to call the sink method to connect the subscribers.
The improved code is below.
import Combine
import Foundation
func delay() -> Future<Void, Error> {
return Future<Void, Error>{ promise in
print("It will be executed")
Thread.sleep(forTimeInterval: 2.0)
promise(.success(()))
return
}
}
func executionDelay() -> AnyPublisher<Void, Error>{
print("I will do it")
return delay()
.handleEvents(receiveSubscription: {_ in
print("Subscription")
}, receiveOutput: { _ in
print("Output")
}, receiveCompletion: { _ in
print("Completion")
}, receiveCancel: {
print("Cancel")
}, receiveRequest: {_ in
print("Request")
})
.eraseToAnyPublisher()
}
//Execute processing
executionDelay()
.sink(receiveCompletion: {completion in
print("receiveCompletion")
switch completion {
case .failure(let error):
print("Failure:\(error)")
default:
print("success")
}
}, receiveValue: { _ in
print("receiveValue")
})