我对FRP很新,我遇到了一个问题:
我订阅了一个每秒触发subscribeNext
的观察者。
在subscribeNext
的块中,I zip
可执行异步操作的可观察对象,并且在zip
的{{1}}块中,我对结果执行操作。
completed
我希望停止触发let signal: RACSignal
let asynchOperations: [RACSignal]
var val: AnyObject?
// subscribeNext is trigered every second
signal.subscribeNext {
let asynchOperations = // several RACSignal
// Perform asynchronous operations
RACSignal.zip(asynchOperations).subscribeNext({
val = $0
}, completed: {
// perform actions with `val`
})
}
subscribeNext
(通常每秒触发一次),直到signal
(来自completed
)。
有什么建议吗?
答案 0 :(得分:1)
听起来你想要RACCommand
。
命令是一个可以执行异步操作的对象,但一次只能运行一个操作实例。一旦您告诉命令启动execute:
,它将被“禁用”,并在操作完成后自动再次启用。
(您还可以根据其他标准创建一个启用的命令,而不仅仅是“我现在正在执行”,但这听起来并不像您需要的那样。)
一旦你有了这个,你可以得到一个“门控”间隔信号的信号(例如,if:then:else:
在命令的enabled
信号之间切换{{1}和你的实际信号 - 我这么做,我有一个帮助器),或者你可以在订阅块中调用RACSignal.empty
之前检查canExecute
属性。
注意:你在内部订阅时做了一些有点奇怪的事情 - 捕获值然后处理已完成块上的值。
如果你这样做是因为它更明确,并且你知道信号只发送一个值,但你觉得需要直接编码,那就没关系。我不认为它是标准的 - 如果你有一个只发送一个值的信号,那不幸的是无法在类型级别表示,但仍然是你可以在你的代码中做出的假设(或者至少,我觉得自己对这个假设感到满意。对每个人都这样做。
但是如果你是出于时间原因而做的,或者因为你实际上只想要从信号发送 last 值,你可以使用execute:
来获得一个信号总是在内部信号完成时恰好发送一个值,然后只在takeLast:1
块中订阅。
轻微警告:next
s用于从主线程用于支持UI更新;如果你想在后台线程上使用命令,你需要明确关于调度程序来发送你的信号(查看文档以获取更多细节)。
获得类似行为的另一种完全不同的方法是时间递归:执行操作,然后在完成后,安排操作在一秒钟后再次发生,而不是持续计时器。
这略有不同,因为你总是在操作之间等待一秒,而在当前的那个你可以等待零到一秒之间的任何地方,但如果这不是问题那么这个是一个比使用RACCommand
更简单的解决方案。
ReactiveCocoa的RACCommand
方法使这种临时调度变得非常方便 - 这里没有人工delay:
争论。