问题描述
我是 Combine 的新手,我不了解这些情况下的行为:
func getPublisherWithFirst() -> AnyPublisher<Value,Error> {
// somePublisher: PassthroughSubject<Bool,Never>
return somePublisher
.compactMap { (someBool) -> Value? in
if someBool {
return Value()
}
return nil
}
.setFailureType(to: Error.self)
.first()
.timeout(.seconds(5),scheduler: dispatchQueue.main)
.erasetoAnyPublisher()
}
func getPublisherWithFlatMap() -> AnyPublisher<Value,Never>
return somePublisher
.flatMap { (someBool) -> AnyPublisher<Value,Never> in
if someBool {
return Just(Value()).erasetoAnyPublisher()
}
return Empty(completeImmediately: false,outputType: Value.self,failureType: Never.self).erasetoAnyPublisher()
}
.setFailureType(to: Error.self)
.timeout(.seconds(5),scheduler: dispatchQueue.main)
.erasetoAnyPublisher()
}
使用 getPublisherWithFlatMap
时,我的流不会结束(触发超时),即使返回了 Just
发布者并且它应该结束。为什么?
解决方法
“问题”是由您使用 PassthroughSubject
作为上游引起的。 PassthroughSubject
永远不会完成,除非您明确发送完成。
使用 first
时,上游是否完成并不重要,因为只要 first
的上游发出单个值,它就会完成。但是,在 flatMap
的情况下,flatMap
对其上游发出的每个值执行其闭包,因此它仅在其上游完成时完成。您在 Just
中返回 flatMap
无关紧要,Just
只会返回单个值,而不是整个上游。
如果您想确保 getPublisherWithFlatMap
在发出单个值后也完成,您也应该对其调用 first
,类似于 getPublisherWithFirst
。
func getPublisherWithFlatMap() -> AnyPublisher<Value,Error> {
// somePublisher: PassthroughSubject<Bool,Never>
return somePublisher
.flatMap { (someBool) -> AnyPublisher<Value,Never> in
if someBool {
return Just(Value()).eraseToAnyPublisher()
}
return Empty(completeImmediately: false,outputType: Value.self,failureType: Never.self).eraseToAnyPublisher()
}
.setFailureType(to: Error.self)
.first()
.timeout(.seconds(5),scheduler: DispatchQueue.main)
.eraseToAnyPublisher()
}