Search code examples
iosobjective-cafnetworkingreactive-cocoaracsignal

Chaining RACSignals and rollback


I'm relatively new to ReactiveCocoa and was wondering how to chain a sequence of REST GET calls together so they perform in order. If one of the calls errors, then the whole process will roll back.

So I'm using pod 'AFNetworking-RACExtensions', '0.1.1' I have a NSArray of signals. Most of these signals look like this:

 - (RACSignal *) form
{
@weakify(self);

RACSubject *repSubject = [RACSubject subject];
[[ServiceClient getForm] subscribeNext:^(RACTuple *jsonTuple) {
    if ([jsonTuple second])
    {
        // create core data objects here            
        [repSubject sendNext: nil];
        [repSubject sendCompleted];
    }
} error:^(NSError *error) {
    [repSubject sendError: error];
}];
return repSubject;     
}

So a load of signals like this are in a NSArray. I want process those calls in the order they appear in array one after another and have a shared error handler and completion block. I think I have had success with not using the nsarray and had code like this:

@weakify(self);
[[[[[[self form] flattenMap:^(id value) {
    // perform your custom business logic
    @strongify(self);
   return [self signal2];
}] flattenMap:^(id value) {
    // perform your custom business logic
    @strongify(self);
    return [self signal3];
}] flattenMap:^(id value) {
    // perform your custom business logic
    @strongify(self);
    return [self signal4];
}] flattenMap:^(id value) {
    // perform your custom business logic
    @strongify(self);
    return [self signal5];
}] subscribeError:^(NSError *error) {
      @strongify(self);
      [self handleError: error];
  } completed:^{
      // Successful Full Sync
      // post notification
  }];    

How can I do all of these with using an NSArray of signals while still being able to use subscribeError and completed blocks?

I'm assuming it's something like:

 @weakify(self);
 [[[array.rac_sequence flattenMap:^RACStream *(id value) {
     // dunno what to do
 }] subscribeError:^(NSError *error) {
      @strongify(self);
      [self handleError: error];
  } completed:^{
      // Successful Full Sync
      // post notification
  }];

Solution

  • First, we convert a RACSequence to a stream-of-streams by - signalWithScheduler:. Then, we can merge stream-of-streams into a signal new stream through - flatten. After that, we can use it as a normal stream.

    And YES, if you don't need to process each response, you can use - subscribeError: completed: of course.

    [[[[array rac_sequence] signalWithScheduler:[RACScheduler immediateScheduler]] flatten] subscribeNext:^(id x) {
        // Handle each results
    } error:^(NSError *error) {
        // Handle error
    } completed:^{
        // Completed
    }];