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

时间:2016-07-15 08:25:35

标签: ios parallel-processing reactive-cocoa

我想并行启动多个独立的网络请求,并在所有请求完成时订阅(我不在乎它们是否已完成或错误)。

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

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

此致

修改

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

我的用例是:

一方面,我有一个可以完全同步的应用程序。这将启动所有独立请求。我需要知道何时完成所有请求才能解除progressHUD。我不在乎我的信号是sendError还是sendCompleted

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

3 个答案:

答案 0 :(得分:1)

我使用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循环,我仍然感兴趣。

答案 1 :(得分:1)

您可以使用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]; 相同,同时使代码更简洁:

import scala.util.parsing.combinator._

class JSON extends JavaTokenParsers {   

  def value : Parser[Any] = obj | arr | 
                        stringLiteral | 
                        floatingPointNumber | 
                        "null" | "true" | "false"

  def obj   : Parser[Any] = "{"~repsep(member, ",")~"}"

  def arr   : Parser[Any] = "["~repsep(value, ",")~"]"

  def member: Parser[Any] = stringLiteral~":"~value
}

答案 2 :(得分:0)

您可以尝试以下代码:

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