0

我目前正在运行基本运算符,并遇到了 combineLatest 运算符的行为差异。我不确定这是一个错误还是我未能理解 Signals 和 SignalProducers 之间的差异。

let (numbersSig, numbersOb) = Signal<Int, NoError>.pipe()
let (lettersSig, lettersOb) = Signal<String, NoError>.pipe()
let signal = combineLatest(numbersSig, lettersSig)
signal.observeNext({value in print(value)})

numbersOb.sendNext(1)
lettersOb.sendNext("A")
lettersOb.sendNext("B")

产生: (1, "A") (1, "B")

但是,如果我使用 SignalProducers 编写我认为等效的代码:

let numberProducer = SignalProducer<Int, NoError> { (observer, disposable) in
    for v in [1] { observer.sendNext(v) }
}

let letterProducer = SignalProducer<String, NoError> { (observer, disposable) in
    for v in ["A", "B", "C", "D"] { observer.sendNext(v) }
}

let combinedProducer = combineLatest(numberProducer, letterProducer)
combinedProducer.on(next: {value in print(value) }).start()

输出:(1,“D”)

我故意将observer.sendCompleted() 排除在SignalProducers 之外,因为我认为这是负责任的,但事实并非如此。我错过了什么?

4

2 回答 2

0

感谢您的建议 NachoSoto。我尝试了您建议的替代方法,并且输出没有改变。当我在 Github repo 上发布这个问题时,我从aromas (Brian Thomas) 那里得到了以下答案:

在 combineProducer 上调用 start 处理在内部字母和数字生产者上调用 start(具体参见 SignalProducer.swift 中的 liftRight,当 otherProducer.startWithSignal 的闭包返回时,它将运行您的 sendNext 代码)。因为它们是同步的,所以字母生产者只是在数字生产者开始返回值之前“下一个”它的所有值。您可以通过在生产者示例中的 combineLatest 方法调用中反转它们来测试这一点。如果您想获得第一次测试的“推送值”行为,请尝试

let (numbersSig, numbersSink) = Signal<Int, NSError>.pipe()
let (lettersSig, lettersSink) = Signal<String, NSError>.pipe()
let numberProducer = SignalProducer(signal: numbersSig)
let letterProducer = SignalProducer(signal: lettersSig)

let combinedProducer = combineLatest(numberProducer, letterProducer)
combinedProducer.on(next: {value in print(value) }).start()

lettersSink.sendNext("A")
numbersSink.sendNext(1)
lettersSink.sendNext("B")
numbersSink.sendNext(2)
lettersSink.sendNext("C")

我尝试按照他的建议反转 numberProducer 和 letterProducer ,输出确实与我最初使用 Signals 遇到的一样,即

let numberProducer = SignalProducer<Int, NoError> { (observer, disposable) in
    for v in [1] { observer.sendNext(v) }
}

let letterProducer = SignalProducer<String, NoError> { (observer, disposable) in
    for v in ["A", "B", "C", "D"] { observer.sendNext(v) }
}

let combinedProducer = combineLatest(letterProducer, numberProducer)
combinedProducer.startWithNext {value in print(value)}

产生: ("A", 1) ("B", 1) ("C", 1) ("D", 1)

您仍然认为这是一个错误或实现行为吗?

于 2016-03-11T14:10:15.970 回答
0

是的,这似乎是一个错误。你介意在 Github 回购上打开一个问题,以便我们可以在那里看看吗?更好的是,如果你能打开一个测试失败的 PR,那就太棒了!:)

我会检查一些可能是解决方法的东西:如果你使用startWithNext而不是on+ ,你会得到相同的结果start吗?

于 2016-03-09T15:28:50.830 回答