如何在没有原始信号被触发两次的情况下订阅一次性信号并有条件地启动辅助信号?

时间:2015-02-04 15:01:26

标签: ios objective-c reactive-programming reactive-cocoa

我想订阅一个网络操作的信号,并有条件地启动辅助网络操作。

我放在一起的代码看起来有点像这样:

RACSignal *asyncWebAPI = [self asyncWebAPI];

@weakify(self)
[asyncWebAPI
 subscribeNext:^(RACTuple *tuple) {
  @strongify(self)
  NSArray *foo = tuple.first;
  [self.bar addObjects:foo];
  self.baz = tuple.second;
 }
 error:^(NSError *error) {
 }];

[[[[asyncWebAPI
    map:^id(RACTuple *tuple) {
      NSArray *foo = tuple.first;
      // Return an array of objects where we want anotherAsyncWebAPI to work with as input
      NSMutableArray *qux = [NSMutableArray array];
      for (id element in foo) {
        if (element.someProperty == -1) {
          [qux addObject:element];
        }
      }
      return [NSArray arrayWithArray:qux];
    }]
   filter:^BOOL(NSArray *qux) {
      // We really only want anotherAsyncWebAPI to perform if the array has elements in it
      return (qux.count != 0);
   }]
  flattenMap:^RACStream *(NSArray *qux) {
      @strongify(self)
      return [self anotherAsyncWebAPI:qux];
  }]
 subscribeNext:^(id x) {
     // subscribe and deal with anotherAsyncWebAPI
 }];

然而,上述情况会导致asyncWebAPI成为热信号两次。

如何在实现第二次Web操作的条件触发器的同时,将上述内容保留为两个独立的管道,而不是单个流畅的管道?

1 个答案:

答案 0 :(得分:0)

对于代码属于同一范围的情况,您可以使用RACSubject分享信号,或使用RACMulticastConnection进行此操作。

使用RACSubject,它看起来像:

RACSubject *webAPISubject = [RACSubject subject];

[webAPISubject subscribeNext:^(RACTuple *tuple) {
    @strongify(self)
    NSArray *foo = tuple.first;
    [self.bar addObjects:foo];
    self.baz = tuple.second;
 }];

[[[[webAPISubject
    map:^id(RACTuple *tuple) { /* ... */ }]
    filter:^BOOL(NSArray *qux) { /* ... */ }]
    flattenMap:^(NSArray *qux) { /* ... */ }]
    subscribeNext:^(id x) { /* ... */ }];

// Open the gates to let the data flow through the above subscriptions
[[self asyncWebAPI] subscribe:webAPISubject];

或者,使用RACMulticastConnection,代码与上面的内容大致相同。主要区别在于开始和结束。

RACMulticastConnection *webAPIConnection = [[self asyncWebAPI] publish];

然后,用asyncWebAPI替换样本中对webAPIConnection.signal的引用。最后,最后致电:

// Open the gates to let the data flow through
[webAPIConnection connect];

从技术上讲,我认为差异不大(RACMulticastConnection在幕后使用RACSubject),这意味着它是一个品味问题。就个人而言,我更喜欢使用这个主题,我认为它更直接。