我如何订阅一次性信号并有条件地启动二次信号而不触发两次原始信号?

How can I subscribe to a one-time signal and conditionally initiate a secondary signal without having the original signal fired twice?

我想订阅一个网络操作的信号,让它有条件地启动第二个网络操作。

我整理的代码看起来有点像这样:

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 操作的条件触发的同时,将上述内容作为两个独立的管道,而不是一个单一的流畅管道?

对于代码在同一范围内的情况,您可以通过使用 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),这意味着这是一个品味问题。就个人而言,我更喜欢使用主题,我认为它更直接。