Search code examples
iosreactive-cocoa

How do I wait in a flattenMap block for a signal to complete before the next event is consumed?


here is my pseudo code :

[[[@[ctx1,ctx2]rac_sequence]signalWithScheduler:RACScheduler.immediateScheduler]

flattenMap:^RACStream *(id ctx) 
{
    // first flatten map
    return [RACSignal createSignal:^(id <RACSubscriber> subscriber) 
    {
        [executeRequestAsynch 
             onDone:^{
             [subscriber sendNext:ctx];  
             [subscriber sendCompleted]; 
    }
    ]

    }]
    flattenMap:^RACStream *(id ctx) {

    // second flattenMap  
    }];

}

Now here is what I want to happen upon subscribe:

1)  ctx1 should get fed to the first flattenMap block
2)  the Server Request "executeRequestAsynch" should be called
3)  on completion of the serverRequest the second flattenMap should be called with ctx1
4)  ctx2 should get fed to the first flattenMap block
5)  the Server Request "executeRequestAsynch" should be called
6)  on completion of the serverRequest the second flattenMap should be called with ctx1

But instead this scenario happens:

1)  ctx1 gets fed to the first flattenMap block
2)  the Server Request "executeRequestAsynch" is called
3)  ctx2 gets fed to the first flattenMap block
4)  the Server Request "executeRequestAsynch" is called
5)   on completion of the serverRequest the second flattenMap is called with ctx1
6)  on completion of the serverRequest the second flattenMap is called with ctx2

How can I make the first scenario happen?


answer this seems to do the work! thanks: output is:

 Step 1
   Step 1 child
     Step 1    child child
 Step 2
   Step 2 child
     Step 2    child child
 done all

I am still wondering what defer will achieve in the underneath senario

-(RACSignal*) executeRequestAsynch:(NSString*) ctx {
 return [RACSignal createSignal:^RACDisposable * (id<RACSubscriber> subscriber) {
     NSLog(@"  %@ child",ctx);
     [subscriber sendCompleted];
                 return nil;
        }];

}

-(RACSignal*) executeRequestAsynch2:(NSString*) ctx {
return [RACSignal createSignal:^RACDisposable * (id<RACSubscriber> subscriber) {
    NSLog(@"  %@    child child",ctx);
    [subscriber sendCompleted];
    return nil;
}];

 }

  - (void)viewDidLoad
{
    [super viewDidLoad];
    RACSignal *contexts = [[@[ @"Step 1", @"Step 2" ] 
    rac_sequence]  signalWithScheduler:RACScheduler.immediateScheduler];
    RACSignal *ne = [[contexts map:^(id ctx) {
    NSLog(@"%@",ctx);
    return [[self executeRequestAsynch:ctx] concat: [self executeRequestAsynch2:ctx ]];}]concat] ;
   [ne subscribeCompleted:^{
    NSLog(@"done all");
}];
}

here is my final real solution


Solution

  • I'm not 100% sure I understand what you're trying to accomplish. My interpretation is something like:

    RACSignal *contexts = [@[ ctx1, ctx2 ] things.rac_sequence signalWithScheduler:RACScheduler.immediateScheduler];
    [[contexts map:^(id ctx) {
        return [executeRequestAsynch concat:[RACSignal defer:^{
            // Returns another signal involving ctx?
        }]];
    }] concat];
    

    This maps each of the context to a executeRequestAsynch, and then concats them so that they are done serially.

    Is that right or did I misunderstand you?