>我有以下简单的Future
:
class ViewModel {
var cancellables = Set<AnyCancellable>()
func test() {
let trigger = PassthroughSubject<Void, Error>()
let future = Future<String, Error> { promise in
promise(.success("Future Succeded"))
}
trigger
.flatMap { future }
.sink(receiveCompletion: { completion in
print("completion received (completion)")
}, receiveValue: { val in
print("value received (val)")
})
.store(in: &cancellables)
trigger.send(())
}
}
我不知道为什么当与另一个发布者(在本例中为PassthroughSubject
(平面映射时它永远不会完成,它只产生值。
当它不是平面映射时,它会生成值并正常完成。
这种行为可能看起来很奇怪,但它很有意义。完成Future
不会完成PassthroughSubject
。因此,您可以继续通过PassthroughSubject
发送值,这将导致创建新的Future
实例并触发。通常,一个Publisher
只能完成或出错一次。因此,如果完成Future
会触发sink
完成闭包,这意味着PassthroughSubject
不能再产生新值,这是不可取的,因为PassthroughSubject
通常永远不会完成(除非你直接告诉它(。
与您的示例类似,此代码也只触发一次完成:
var cancellables = Set<AnyCancellable>()
(0..<2).publisher
.flatMap { _ in return (0..<5).publisher }
.sink(receiveCompletion: { completion in
print("completion received (completion)")
}, receiveValue: { val in
print("value received (val)")
})
.store(in: &cancellables)
原因是创建的发布者是将发布两个值的发布者,然后完成。如果flatMap
发布者会导致调用sink
完成,则意味着(0..<2)
发布者完成,只是它仍有要发送的值,因此未完成。
长话短说,开始发布者决定流何时完成,而不是平面映射发布者。
我以为我遇到了这个问题,但事实证明这只是因为我没有保留发布者的返回值。如sink()
文档中所述
应保留返回值,否则流将被取消。
我的游乐场代码:
var t:Timer?
print(Date())
let _ = Just(33)
.flatMap { (i) -> Future<Int, Never> in
return Future<Int, Never> { promise in
t = Timer.scheduledTimer(withTimeInterval: 1, repeats: false) { (t) in
print("Timer!")
promise(.success(i * i))
}
}
}
.sink { (i) in
print("ok")
print("(Date()): (i) received")
}
计时器触发,但未调用接收器。将分配更改为 ...
let pub = Just(33)
。解决了它。