观察事件在反应堆中传递

时间:2019-05-17 03:30:07

标签: swift reactive-programming reactive-swift

我已经阅读了多次文档,需要澄清...

给出以下代码段:

let signal: Signal<Value,Error>

//call this observer y
signal.take(first: 1).observeValues{ (value) in
  //intended strong capture on self. this is the only one that retains self so if this observer is triggered and completes, self should dealloc
 self.doSomethingElse(value) //trivial call, no async or thread hopping
}

//call this observer x
signal.take(duringLifetimeOf: self).observeValues{ [unowned self] (value) in //is this safe or better to use weak and guard against it? 
   self.doSomeProcess(value) //trivial call, no async or thread hopping
}

如果signal被触发并向其观察者通知value event

1)观察者y会在x之前得到通知(假设是因为首先在队列中更早地观察到它)

2)由于y将在处理完该值之后完成,因此self随后应取消分配

问题:

x会收到哪些事件(按顺序):

  • 值和完成度?是否可以保证在处理value事件时self仍然存在?

  • 仅完成?我怀疑是这种情况,但请参考一些文档。因为完成事件不会立即传播。

Schedulerx是否使用不同的y会对结果产生影响?

最后,我要介绍race吗?我对此表示怀疑,因为除非开发人员明确声明,否则reactSwift不会引入并发。

1 个答案:

答案 0 :(得分:1)

我整理了一个示例控制台应用程序来进行测试。正如我在评论中所述,take(first: 1)在传递1值事件后立即立即同步完成事件,这意味着yself的引用将在任何值传递给x。假设这是对self的唯一强引用,则x将不会收到任何值。

import Foundation
import ReactiveSwift
import ReactiveCocoa

class MyClass {
    init(signal: Signal<String, Never>) {
        //call this observer y
        signal.take(first: 1).observeValues{ (value) in
            //intended strong capture on self. this is the only one that retains self so if this observer is triggered and completes, self should dealloc
            self.doSomethingElse(value) //trivial call, no async or thread hopping
        }

        //call this observer x
        signal.take(duringLifetimeOf: self).observeValues{ [unowned self] (value) in //is this safe or better to use weak and guard against it?
            self.doSomeProcess(value) //trivial call, no async or thread hopping
        }
    }

    func doSomethingElse(_ value: String) {
        print("Something Else: \(value)")
    }

    func doSomeProcess(_ value: String) {
        print("Some Process: \(value)")
    }
}

let (signal, input) = Signal<String, Never>.pipe()
_ = MyClass(signal: signal)

input.send(value: "1")
input.send(value: "2")

当然,doSomeProcess从未被调用:

Something Else: 1
Program ended with exit code: 0

要记住的关于ReactiveSwift的关键是,除非您用一组特定的运算符或您自己的代码另外明确指定,否则所有操作都是同步发生的。因此,take运算符不会随同发送一个value事件,而是以某种方式“安排”完成事件的交付以供以后使用。价值事件和完成事件的交付均发生在上游信号交付价值事件的过程中,而观察者及其引用的解除分配发生在signal完成其第一个事件的交付之前。

当您说“完成事件不会立即传播”时,我假设您是在谈论APIContracts file的那一部分,该部分讨论了如何立即传播故障和中断。这只是在指出,即使是异步或时移运算符,许多运算符也会立即传递这些事件。

take运算符不是时移或异步运算符。并且在这种情况下,操作员不会从上游信号传播完成事件;相反,它是生成完成事件本身,以及it is doing so synchronously immediately after it propagates the value event

我要介绍一场比赛吗?

您是正确的,ReactiveSwift不会单独引入异步或并发性,因此在传统意义上这里没有“竞赛”。但是,我相信Signal的API合约不能保证事件以观察者开始观察的顺序传递给观察者。因此,此代码的行为在技术上是未定义的,并且可能在ReactiveSwift的未来版本中更改。

对x和y使用不同的调度程序会对结果产生影响吗?

现在这实际上将引发一场比赛,因为take的完成事件将在您为该观察者设置的任何调度程序上传递,并且该事件的传递将触发{{1}的deinit }。