简体   繁体   中英

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

I would like to subscribe to a signal of one web operation and have it conditionally initiate a secondary web operation.

The code I have put together looks a little like this:

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
 }];

The above, however, causes the asyncWebAPI to become a hot signal twice.

How can I keep the above as two separate pipelines, as opposed to a single fluent pipeline, while achieving the conditional trigger of a second web operation?

For cases where the code is in the same scope, you could go about this in by using a RACSubject to share the signal, or by using a RACMulticastConnection .

Using a RACSubject , it would look like:

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];

Alternatively, using a RACMulticastConnection , the code will looks much the same as above. The primary difference being the beginning and end.

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

then, replace the references to asyncWebAPI in your sample with webAPIConnection.signal . Finally, at the end, call:

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

Technically, I don't think there's much of a difference (the RACMulticastConnection uses RACSubject s behind the scenes), which means it's a matter of taste. Personally, I prefer the use of the subject, I see it as more straightforward.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM