Reactive Cocoa Legacy - 如何并行处理多个独立信号?

Reactive Cocoa Legacy - How to handle multiple independent signals in parallel?

我想并行发起多个独立的网络请求,并订阅所有请求何时完成(我不关心它们是完成还是错误)。

目前,我使用 combineLatest。因此,请求是并行发出的(如我所愿),但是当信号发送时 error,我在订阅中遇到错误。

我找不到允许我并行启动多个独立请求并在所有完成时监听的运算符。

此致

编辑

在其他情况下(我需要单独使用信号),我需要订阅错误。所以我仍然需要我的信号才能 sendError:.

我的用例是这样的:

一方面,我有一个可以进行完全同步的应用程序。这将启动所有独立请求。我需要知道所有请求何时完成才能关闭 progressHUD。我不在乎我的信号是否完成 sendErrorsendCompleted.

但另一方面,我有多个按钮,我可以在其中单独重新启动每个请求,在这种情况下,我需要告诉用户信号是成功还是失败。

您可以试试这个代码:

- (void)getAllItemsWithCompletion:(void (^)())completion {
        NSArray *signals = [self.allItems.rac_sequence map:^id(Item *item)  {
          return [[[self getForItemSignal:item] doCompleted:^{
                         //done
                    }] doError:^(NSError *error) {
                         //Change the button title to retry
                    }];
     }].array;

  [[RACSignal combineLatest:signals] subscribeCompleted:^{
     NSLog(@"All tasks are done");
  }];
}

- (RACSignal *)getForItemSignal:(Item *)item {
return [RACSignal startEagerlyWithScheduler:[RACScheduler scheduler] block:^(id<RACSubscriber> subscriber) {
        [APIClient getFeeForItemUUID:item.UUID
                         success:^(Fee *fee) {
                             [subscriber sendNext:@(fee)];
                             [subscriber sendCompleted];
                         }
                         failure:^(NSError *error) {
                             [subscriber sendError:error];
                             [subscriber sendCompleted];
                         }];
   }];
}

我想出了一个答案,使用 catch 运算符: 我将 catch RAC 运算符添加到我的所有信号中,这会生成一个新的 [RACSignal empty] 以防信号失败:

NSArray* allSignals = @[signal1, signal2, signal3, signal4];
NSMutableArray* optionalSignals = [NSMutableArray array];
    for (RACSignal* signal in allSignals) {
        RACSignal* catchableSignal = [signal catch:^RACSignal *(NSError *error) {
            return [RACSignal empty];
        }];
        [optionalSignals addObject:catchableSignal];
    }

return [RACSignal combineLatest:optionalSignals];

这不会改变我个人信号的性质,我受益于 combineLatest 功能。

编辑

如果有人有更优雅的 RAC 方式来处理 for...in 循环,我仍然很感兴趣。

您可以使用 rac_sequencemap 而不是循环。此外,在您的情况下,使用 catchTo 将以与 catch 相同的方式工作,同时使代码更简洁:

NSArray* allSignals = @[signal1, signal2, signal3, signal4];
RACSequence *optionalSignals = [[allSignals rac_sequence] map:^id(RACSignal *signal) {
            return [signal catchTo:[RACSignal empty]];
}];

return [RACSignal combineLatest:optionalSignals];