ReactiveCocoa - 订阅第二个信号,如果第一个信号没有值完成
ReactiveCocoa - Subscribe to the second signal, if the first completes with no value
假设我有两个信号:一个便宜的和一个昂贵的:
RACSignal *localSignal; // Cheap signal. Sends object without network request
// if possible, otherwise completes immediately.
RACSingal *networkSignal; // Expensive one. Always sends data,
// but requires expensive network operation.
现在我想创建一个信号,它从第一个信号(如果有)发送值,或者订阅第二个信号并从该信号发送数据。
下面的解决方案几乎可以满足我的需求,但它总是订阅第二个昂贵的信号,即使第一个信号的值被采用,第二个信号的值被忽略。
[[localDataSignal concat:networkDataSignal] take:1];
有没有高效解决问题的方法?
您可以使用:
- (RACSignal *)catchTo:(RACSignal *)signal;
像这样:
[[localSignal catchTo:networkSignal] subscribeNext:^(id x) {
// If localSignal sends error, networkSignal will be subscribed.
}];
我刚刚发现问题所在。本地信号使用创建和调用它的同一线程:
RACSignal *localSignal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
NSLog(@"Perfoming local operation");
[subscriber sendNext:@"local value"];
[subscriber sendCompleted];
return nil;
}];
正如我看到的问题(我不确定 100%)take:1 甚至没有机会处理连接的网络信号。但是,如果我在不同于主线程调度程序的地方安排本地信号,那么 take:1 会按预期工作——它会在获得第一个值后中断链。
简单来说,这段代码有效:
[[[localSignal deliverOn:[RACScheduler scheduler]] concat:networkSignal] take:1]
它给了我我想要的东西:本地信号的值,如果有的话,或者订阅网络信号并给我它的值。如果本地信号发送值,网络信号永远不会被订阅。
经验法则是检查信号工作的线程,然后 take:1 应该按预期工作。
更新: -deliveOnMainThread
也给了 -take:
处理队列的机会。
有点难看,但是在网络信号之前,concat一个有延迟的空信号。我没试过这个,但它应该引入允许 take
防止在 localSignal
发送值的情况下订阅 networkSignal
所需的异步。此方法不会影响 localSignal
.
值的传递
[[RACSignal concat:@[
localSignal,
[[RACSignal empty] deliverOn:RACScheduler.mainThreadScheduler],
networkSignal
] take:1]
作为 deliverOn:
的替代方案,您可以考虑 delay:
如果这样可以使这段代码更容易理解。
假设我有两个信号:一个便宜的和一个昂贵的:
RACSignal *localSignal; // Cheap signal. Sends object without network request
// if possible, otherwise completes immediately.
RACSingal *networkSignal; // Expensive one. Always sends data,
// but requires expensive network operation.
现在我想创建一个信号,它从第一个信号(如果有)发送值,或者订阅第二个信号并从该信号发送数据。
下面的解决方案几乎可以满足我的需求,但它总是订阅第二个昂贵的信号,即使第一个信号的值被采用,第二个信号的值被忽略。
[[localDataSignal concat:networkDataSignal] take:1];
有没有高效解决问题的方法?
您可以使用:
- (RACSignal *)catchTo:(RACSignal *)signal;
像这样:
[[localSignal catchTo:networkSignal] subscribeNext:^(id x) {
// If localSignal sends error, networkSignal will be subscribed.
}];
我刚刚发现问题所在。本地信号使用创建和调用它的同一线程:
RACSignal *localSignal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
NSLog(@"Perfoming local operation");
[subscriber sendNext:@"local value"];
[subscriber sendCompleted];
return nil;
}];
正如我看到的问题(我不确定 100%)take:1 甚至没有机会处理连接的网络信号。但是,如果我在不同于主线程调度程序的地方安排本地信号,那么 take:1 会按预期工作——它会在获得第一个值后中断链。
简单来说,这段代码有效:
[[[localSignal deliverOn:[RACScheduler scheduler]] concat:networkSignal] take:1]
它给了我我想要的东西:本地信号的值,如果有的话,或者订阅网络信号并给我它的值。如果本地信号发送值,网络信号永远不会被订阅。
经验法则是检查信号工作的线程,然后 take:1 应该按预期工作。
更新: -deliveOnMainThread
也给了 -take:
处理队列的机会。
有点难看,但是在网络信号之前,concat一个有延迟的空信号。我没试过这个,但它应该引入允许 take
防止在 localSignal
发送值的情况下订阅 networkSignal
所需的异步。此方法不会影响 localSignal
.
[[RACSignal concat:@[
localSignal,
[[RACSignal empty] deliverOn:RACScheduler.mainThreadScheduler],
networkSignal
] take:1]
作为 deliverOn:
的替代方案,您可以考虑 delay:
如果这样可以使这段代码更容易理解。