2

I have 2 network signals and the first one needs to complete before the next one starts because I need to send an accessToken for the second request and I obtain that in the first request. Then I want to reduce the values from each step into a single object. I guess combineLatest:reduce: subscribes to both of them and has nothing to do with waiting completion of signal.

I have this right now:

- (RACSignal *)loginWithEmail:(NSString *)email password:(NSString *)password
{
    @weakify(self);
    RACSignal *authSignal = [[self requestTokensWithUsername:email password:password]  
        doNext:^(Authentication *auth) {
            @strongify(self);
            self.authentication = auth;  
        }];

    RACSignal *profileSignal = [self fetchProfile];
    NSArray *orderedSignals = @[ authSignal, profileSignal ];
    RACSignal *userSignal =
        [RACSignal combineLatest:orderedSignals
                          reduce:^id(Authentication *auth, Profile *profile) {
                              NSLog(@"combine: %@, %@", auth, profile);
                              return [User userWithAuth:auth profile:profile history:nil];
                          }];

    return [[[RACSignal concat:orderedSignals.rac_sequence] collect]
        flattenMap:^RACStream * (id value) {                
            return userSignal;
        }];
}

To ensure that they are done in order, I return a signal where I first concat: the signals, then collect them to send completed only when all of the signals complete, and flattenMap: to a combineLatest:reduce: to process latest result from each.

It works but I think there might be a more concise and better way to do this. How might I rewrite this part to make it more concise maybe?

akaralar
  • 1,103
  • 1
  • 10
  • 29

2 Answers2

2

Take look at - (RACSignal*)then:(RACSignal*(^)(void))block; I think it perfectly fits to your case. For example:

RACSignal* loginSignal = [[self authenticateWithUsername:username password:password] doNext:...];

RACSignal *resultSignal = [loginSignal then:^RACSignal* {
      return [self fetchProfile];
  }];
return resultSignal;
hybridcattt
  • 3,001
  • 20
  • 37
  • 2 more requests will be added there, so i'm looking to do it without having to type out then's. what do you think? – akaralar May 12 '15 at 21:07
  • I think then: is best for it because on completion of the receiver signal then block is called and subscription is made to returned signal. And you can have as many then's as you need – hybridcattt May 12 '15 at 21:18
  • what about accumulating next values from each signal in a final step? is there a way to do it that you can think of? – akaralar May 12 '15 at 21:57
1

FWIW, I simplified my code to this and somewhat happy with the results. I'm leaving it here for future reference.

- (RACSignal *)loginWithEmail:(NSString *)email password:(NSString *)password
{
    @weakify(self);
    RACSignal *authSignal = [[self requestTokensWithUsername:email password:password]  
        doNext:^(Authentication *auth) {
            @strongify(self);
            self.authentication = auth;  
        }];

    RACSignal *profileSignal = [self fetchProfile];
    RACSignal *historySignal = [self fetchHistory];
    RACSignal *balanceSignal = [self fetchBalanceDetails];

    NSArray *orderedSignals = @[ authSignal, balanceSignal, profileSignal, historySignal ];

    return [[[RACSignal concat:orderedSignals.rac_sequence]  
        collect]                                              
        map:^id(NSArray *parameters) {

            return [User userWithAuth:parameters[0]
                              balance:parameters[1]
                              profile:parameters[2]
                              history:parameters[3]];
        }];
}
akaralar
  • 1,103
  • 1
  • 10
  • 29
  • To fit in with RAC design methodologies you should really be using `then:`. – Charles Maria May 14 '15 at 02:31
  • @LowlyDeveloper how so? Can you point me to the source of this information? ie. Why using concat and collect does not with with that philosophy but using then does fit? – akaralar May 14 '15 at 08:54
  • @LowlyDeveloper, concat rac_sequence is perfectly in the RAC design methodologies. Check out http://stackoverflow.com/questions/18907682/chaining-asynchronous-operations-from-an-array-of-objects-with-reactivecocoa – ZpaceZombor Aug 31 '15 at 10:10