合并和减少,但在订阅下一个信号之前等待每个信号完成

Combine and reduce but wait for each signal to complete before subscribing to next one

我有 2 个网络信号,第一个需要在下一个开始之前完成,因为我需要为第二个请求发送 accessToken,我在第一个请求中获得了它。然后我想将每个步骤的值减少到一个对象中。我想 combineLatest:reduce: 订阅了他们两个,与等待信号完成无关。

我现在有这个:

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

为了确保它们按顺序完成,我 return 一个信号,我首先 concat: 信号,然后 collect 它们仅在所有信号完成时才发送完成, 和 flattenMap:combineLatest:reduce: 以处理每个的最新结果。

它有效,但我认为可能有更简洁、更好的方法来做到这一点。我该如何重写这部分以使其更简洁?

看看- (RACSignal*)then:(RACSignal*(^)(void))block; 我认为它非常适合您的情况。 例如:

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

RACSignal *resultSignal = [loginSignal then:^RACSignal* {
      return [self fetchProfile];
  }];
return resultSignal;

FWIW,我将我的代码简化为这个并且对结果有些满意。我把它留在这里供将来参考。

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