ReactiveSwift 链式 SignalProducer 不会将完成发送到下游



因为我是响应式编程的新手,所以我对在ReactiveSwift中链接SignalProducers有一些初学者问题。我的目标是创建一个 SignalProducer 链,以测试我的一个流。在做SignalProducer链接时,我偶然发现了一个障碍。如果我最里面的 SignalProducer 正在调用 sendComplete,它将不会传播到下游。这是游乐场中的模拟代码

private func doSomethingWithString() -> SignalProducer<Int, Error> {
return SignalProducer<String, Error> {observer, _ in
observer.send(value: "Hello")
}.flatMap(.latest, doSomethingWithInt(string:))
}
private func doSomethingWithInt(string: String) -> SignalProducer<Int, Error> {
return SignalProducer<Int, Error> { observer, _ in
observer.send(value: 2)
observer.sendCompleted()
}
}
func test() -> SignalProducer<Int,Error> {
return doSomethingWithString()
}
func leGo() {
test().start { (event) in
switch event {
case .completed:
print("DONE")
case .value(let value):
print("WE HAVE A VALUE: (value)")
case.interrupted:
print("INTERRUPTED")
case .failed(let error):
print("FAILED (error)")
}
}
}
leGo()

在此代码段中,值按预期打印"我们有一个值 2",但从未执行 COMPLETE,因此永远不会打印"DONE"。 如果有人解释为什么会这样以及如何正确做到这一点,我将不胜感激。我可以通过在doSomethingWithString中调用sendCompleted()来使其工作,但由于我的原始流有 2 个以上的方法,我不想在每个方法中编写它。另外.take(first:1)对我来说听起来很奇怪的选项,因为我真的不想通过所有链条来拿走 1 件物品。相反,如果可能的话,我想在一个地方一次性终止整个流。

flatMap

的目的是将每个传入的值转换为新的生产者,然后根据某种策略将这些内部生产者的值平展为单个流。当内部生产者完成时,它不会发送已完成的事件,原因很简单,你可以有多个内部生产者,如果它在其内部生产者之一完成时完成,您将错过所有其他内部生产者的值。

因此,答案是,如果您希望完成整个流,则外部创建者必须发送已完成的事件。

下面是一个常用flatMap的示例,希望能说明为什么flatMap以这种方式工作:

let searchResults = searchText
.flatMap(.latest) { text in
performSearch(for: text)
}

searchResults信号旨在每次用户更改搜索文本时更新新结果。因此,您不希望流仅仅因为其中一个搜索完成而完成;您希望在用户更改文本时启动新搜索并更新结果。

您可以为SignalProducer编写某种帮助程序初始值设定项,该初始值设定项使用take(first: 1)在单个值后自动完成,但更习惯的做法是让所有生成者在完成后正确发送完成事件。

相关内容

  • 没有找到相关文章

最新更新