【问题标题】:Combine and reduce but wait for each signal to complete before subscribing to next one合并和减少,但要等待每个信号完成,然后再订阅下一个
【发布时间】:2015-05-12 18:54:43
【问题描述】:

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

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

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

【问题讨论】:

    标签: ios objective-c reactive-cocoa


    【解决方案1】:

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

    RACSignal* loginSignal = [[self authenticateWithUsername:username password:password] doNext:...];
    
    RACSignal *resultSignal = [loginSignal then:^RACSignal* {
          return [self fetchProfile];
      }];
    return resultSignal;
    

    【讨论】:

    • 将在此处添加 2 个请求,因此我希望无需输入 then 即可。你怎么看?
    • 我认为 then: 最适合它,因为在接收器信号完成后,将调用块并订阅返回的信号。您可以根据需要拥有尽可能多的 then's
    • 在最后一步从每个信号中累积下一个值怎么样?有没有你能想到的方法?
    【解决方案2】:

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

    【讨论】:

    • 要适应 RAC 设计方法,您应该真正使用 then:
    • @LowlyDeveloper 怎么会这样?你能指出这些信息的来源吗? IE。为什么使用 concat 和 collect 不符合这种理念,但使用 then 却适合?
    • @LowlyDeveloper,concat rac_sequence 完全符合 RAC 设计方法。查看stackoverflow.com/questions/18907682/…
    猜你喜欢
    • 1970-01-01
    • 2020-04-14
    • 2019-08-01
    • 1970-01-01
    • 2016-06-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多