ReactiveSwift 中平面图策略之间的差异
Differences among flatmap strategies in ReactiveSwift
从 reactive swift 的文档中我可以理解 Flattening
。可以找到其中的示例 here。在Flattening event streams
一节中,一切都讨论得很完美。
我对 flatmap
感到困惑。根据文档,它 Maps each event from self to a new producer, then flattens the resulting producers according to strategy - concat/merge/latest
。所以,它应该类似于 flattening
我猜。
但是,我无法生成类似的行为。例如考虑以下代码段。如果我像 concat/merge/latest
那样改变展平策略,输出不会改变。
let (numbersSignal, numbersObserver) = Signal<String, NoError>.pipe()
numbersSignal.producer.flatMap(.concat) { value -> SignalProducer<String, NoError> in
print("Outer Signal Producer \(value)")
return SignalProducer<String, NoError> {
observer, lifetime in
print("Inner Signal Producer \(value)")
observer.send(value: "Inner")
observer.sendCompleted()
}
}.observe(on: UIScheduler()).startWithValues { result in
print("Observer \(result)")
}
numbersObserver.send(value: "A")
numbersObserver.send(value: "B")
numbersObserver.send(value: "C")
numbersObserver.sendCompleted()
输出:
Outer Signal Producer A
Inner Signal Producer A
Observer Inner
Outer Signal Producer B
Inner Signal Producer B
Observer Inner
Outer Signal Producer C
Inner Signal Producer C
Observer Inner
谁能解决这个问题?
此外,能否提供任何关于flatmap
区分merge, concat, latest
效果的例子?
这里发生的是您在 flatMap
中创建的生产者同步完成;您在开始闭包本身内调用 sendCompleted
。因此在 flatMap
内,它在生产者上调用 start
,生产者在调用 start
甚至 returns 之前完成。这意味着 flatMap
没有机会应用不同的策略;每个生产者在启动后立即完成。
我们可以通过在 flatMap
中创建一个异步生产者来了解不同策略的行为方式(注意我使用的是最新版本的 Swift 和 ReactiveSwift,所以我我正在使用 Never
而不是 NoError
):
let (numbersSignal, numbersObserver) = Signal<TimeInterval, Never>.pipe()
numbersSignal.producer
.flatMap(.concat) { value -> SignalProducer<TimeInterval, Never> in
print("Outer Signal Producer \(value)")
return SignalProducer(value: value).delay(value, on: QueueScheduler())
}
.startWithValues { result in
print("Observer \(result)")
}
numbersObserver.send(value: 5)
numbersObserver.send(value: 2)
numbersObserver.send(value: 1)
在此示例中,我们将发送 TimeInterval
个值,并且每个创建的生产者发送给定值的延迟等于该值。
concat: 每个后续的生产者在开始之前等待前一个生产者完成,因此值按照我们发送它们的确切顺序打印。
Outer Signal Producer 5.0
Outer Signal Producer 2.0
Outer Signal Producer 1.0
Observer 5.0
Observer 2.0
Observer 1.0
合并: 一旦我们发送值,所有生产者都会立即启动,因此它们都是 运行 同时发生的。因此,值从小到大打印,即延迟最短的生产者首先完成。
Outer Signal Producer 5.0
Outer Signal Producer 2.0
Outer Signal Producer 1.0
Observer 1.0
Observer 2.0
Observer 5.0
latest: 只打印最后一个值,因为每个生产者在新值进来时被取消;只允许最后一个值 运行 完成。
Outer Signal Producer 5.0
Outer Signal Producer 2.0
Outer Signal Producer 1.0
Observer 1.0
请注意,在所有三种情况下,首先为所有值打印 "Outer Signal Producer" 消息。这是因为我们给flatMap
的闭包总是在有新值进来的时候运行。但是产生的producer是按照flatten策略启动和取消的。
从 reactive swift 的文档中我可以理解 Flattening
。可以找到其中的示例 here。在Flattening event streams
一节中,一切都讨论得很完美。
我对 flatmap
感到困惑。根据文档,它 Maps each event from self to a new producer, then flattens the resulting producers according to strategy - concat/merge/latest
。所以,它应该类似于 flattening
我猜。
但是,我无法生成类似的行为。例如考虑以下代码段。如果我像 concat/merge/latest
那样改变展平策略,输出不会改变。
let (numbersSignal, numbersObserver) = Signal<String, NoError>.pipe()
numbersSignal.producer.flatMap(.concat) { value -> SignalProducer<String, NoError> in
print("Outer Signal Producer \(value)")
return SignalProducer<String, NoError> {
observer, lifetime in
print("Inner Signal Producer \(value)")
observer.send(value: "Inner")
observer.sendCompleted()
}
}.observe(on: UIScheduler()).startWithValues { result in
print("Observer \(result)")
}
numbersObserver.send(value: "A")
numbersObserver.send(value: "B")
numbersObserver.send(value: "C")
numbersObserver.sendCompleted()
输出:
Outer Signal Producer A
Inner Signal Producer A
Observer Inner
Outer Signal Producer B
Inner Signal Producer B
Observer Inner
Outer Signal Producer C
Inner Signal Producer C
Observer Inner
谁能解决这个问题?
此外,能否提供任何关于flatmap
区分merge, concat, latest
效果的例子?
这里发生的是您在 flatMap
中创建的生产者同步完成;您在开始闭包本身内调用 sendCompleted
。因此在 flatMap
内,它在生产者上调用 start
,生产者在调用 start
甚至 returns 之前完成。这意味着 flatMap
没有机会应用不同的策略;每个生产者在启动后立即完成。
我们可以通过在 flatMap
中创建一个异步生产者来了解不同策略的行为方式(注意我使用的是最新版本的 Swift 和 ReactiveSwift,所以我我正在使用 Never
而不是 NoError
):
let (numbersSignal, numbersObserver) = Signal<TimeInterval, Never>.pipe()
numbersSignal.producer
.flatMap(.concat) { value -> SignalProducer<TimeInterval, Never> in
print("Outer Signal Producer \(value)")
return SignalProducer(value: value).delay(value, on: QueueScheduler())
}
.startWithValues { result in
print("Observer \(result)")
}
numbersObserver.send(value: 5)
numbersObserver.send(value: 2)
numbersObserver.send(value: 1)
在此示例中,我们将发送 TimeInterval
个值,并且每个创建的生产者发送给定值的延迟等于该值。
concat: 每个后续的生产者在开始之前等待前一个生产者完成,因此值按照我们发送它们的确切顺序打印。
Outer Signal Producer 5.0
Outer Signal Producer 2.0
Outer Signal Producer 1.0
Observer 5.0
Observer 2.0
Observer 1.0
合并: 一旦我们发送值,所有生产者都会立即启动,因此它们都是 运行 同时发生的。因此,值从小到大打印,即延迟最短的生产者首先完成。
Outer Signal Producer 5.0
Outer Signal Producer 2.0
Outer Signal Producer 1.0
Observer 1.0
Observer 2.0
Observer 5.0
latest: 只打印最后一个值,因为每个生产者在新值进来时被取消;只允许最后一个值 运行 完成。
Outer Signal Producer 5.0
Outer Signal Producer 2.0
Outer Signal Producer 1.0
Observer 1.0
请注意,在所有三种情况下,首先为所有值打印 "Outer Signal Producer" 消息。这是因为我们给flatMap
的闭包总是在有新值进来的时候运行。但是产生的producer是按照flatten策略启动和取消的。