【问题标题】:ReactiveCocoa catch all the errors - async network operation on collection objectReactiveCocoa 捕获所有错误 - 集合对象上的异步网络操作
【发布时间】:2014-01-27 04:13:42
【问题描述】:

我刚刚开始学习反应可可。我想对集合对象中的每个条目进行网络操作并解析返回结果,如果报告错误,则将该条目标记为无效。

下面的例子说明了这个问题。 urlList 数组有 4 个条目。2 个条目生成错误(生成连接关闭和超时错误)。所以所有条目都不会通知订阅块。

- (RACSignal *)processStationList
{
    NSArray *urlList = @[@"http://66.55.93.205/listen.pls",@"http://84.20.77.50:8000/listen.pls",@"http://valekalter.serverroom.us:9264/listen.pls", @"http://66.55.93.205:8080/listen.pls"];

    return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        [[urlList.rac_sequence.signal flattenMap:^RACStream *(NSString *urlString) {
            NSLog(@"flatten map %@",urlString);
            return [self fetchStationURLListForStation:urlString];
        }] subscribeNext:^(id x) {
            NSLog(@"suscribe next %@",x);
            [subscriber sendNext:x];
        } error:^(NSError *error) {
            NSLog(@"suscribe error %@",error);
            [subscriber sendNext:nil];
        } completed:^{
            NSLog(@"completed");
            [subscriber sendCompleted];
        }];
        return nil;
    }];
}
    - (RACSignal *)fetchStationURLListForStation:(NSString *)urlString
    {
        NSURL *url = [NSURL URLWithString:urlString];
        NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url];
        return [[NSURLConnection rac_sendAsynchronousRequest:urlRequest] map:^(RACTuple *value) {

        // for simplicity i have commented the following method which parses the .pls data to extract the
       // URL List and returing hard coded URL list
       //  return [self processStationURLData:[value second]];
          return @[@"http://66.55.93.205",@"http://66.55.93.205"];
        }];
    }

输出:

2014-01-27 10:49:27.108 Playground[6566:1303] flatten map http://66.55.93.205/listen.pls
2014-01-27 10:49:27.112 Playground[6566:1303] flatten map http://84.20.77.50:8000/listen.pls
2014-01-27 10:49:27.120 Playground[6566:1303] flatten map http://valekalter.serverroom.us:9264/listen.pls
2014-01-27 10:49:27.121 Playground[6566:1303] flatten map http://66.55.93.205:8080/listen.pls
2014-01-27 10:49:27.641 Playground[6566:3603] suscribe next (
    "http://66.55.93.205:80/"
)
2014-01-27 10:49:27.641 Playground[6566:3603] suscribe next (
    "http://66.55.93.205:8080/"
)
2014-01-27 10:50:27.161 Playground[6566:4103] suscribe error Error Domain=NSURLErrorDomain Code=-1001 "The request timed out." UserInfo=0x8b6efe0 {NSErrorFailingURLStringKey=http://valekalter.serverroom.us:9264/listen.pls, NSErrorFailingURLKey=http://valekalter.serverroom.us:9264/listen.pls, NSLocalizedDescription=The request timed out., NSUnderlyingError=0x8b6e520 "The request timed out."}

我希望为集合中的所有条目通知 subscribeNext/Error 块,以便我可以将条目标记为有效或无效。

如何使用反应可可来实现它。

更新

我已尝试将订阅块替换为如下所示的 catch 块。它只捕获第一个错误事件。

- (RACSignal *)processStationList
{
    NSArray *urlList = @[@"http://66.55.93.205/listen.pls",@"http://84.20.77.50:8000/listen.pls",@"http://valekalter.serverroom.us:9264/listen.pls", @"http://66.55.93.205:8080/listen.pls"];

    return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        [[[urlList.rac_sequence.signal flattenMap:^RACStream *(NSString *urlString) {
            NSLog(@"flatten map %@",urlString);
            return [self fetchStationURLListForStation:urlString];
        }] catch:^RACSignal *(NSError *error) {
            NSLog(@"catch %@",error);
            return [RACSignal empty];
        }] subscribeNext:^(id x) {
            NSLog(@"subscribe next %@",x);
        }];
        return nil;
    }];
}

输出:

2014-01-27 10:55:45.801 Playground[6648:1303] flatten map http://66.55.93.205/listen.pls
2014-01-27 10:55:45.806 Playground[6648:1303] flatten map http://84.20.77.50:8000/listen.pls
2014-01-27 10:55:45.814 Playground[6648:1303] flatten map http://valekalter.serverroom.us:9264/listen.pls
2014-01-27 10:55:45.814 Playground[6648:1303] flatten map http://66.55.93.205:8080/listen.pls
2014-01-27 10:55:46.401 Playground[6648:3603] subscribe next (
    "http://66.55.93.205:8080/"
)
2014-01-27 10:55:46.402 Playground[6648:3603] subscribe next (
    "http://66.55.93.205:80/"
)
2014-01-27 10:55:57.728 Playground[6648:5007] catch Error Domain=NSURLErrorDomain Code=-1004 "Could not connect to the server." UserInfo=0x8b61730 {NSErrorFailingURLStringKey=http://valekalter.serverroom.us:9264/listen.pls, NSErrorFailingURLKey=http://valekalter.serverroom.us:9264/listen.pls, NSLocalizedDescription=Could not connect to the server., NSUnderlyingError=0x8b60f70 "Could not connect to the server."}

如何捕获所有错误?

【问题讨论】:

  • processStationURLData 有什么特别之处可以使您的示例正常工作吗?请您至少提供存根代码吗?
  • 我刚刚更新了问题以返回硬编码的 URL 列表数组。基本上 processStationURLData 方法处理数据以提取 URL 列表。 .pls 文件可能包含多个 URL,因此该函数返回 URL 字符串数组

标签: objective-c cocoa reactive-cocoa


【解决方案1】:

当您的 -fetchStationURLListForStation: 函数在其订阅者上调用 -sendError: 时,它也会结束信号。这里最外层的订阅者捕捉到了错误,所以整个外层的信号也结束了。

一种可能性是在您对-fetchStationURLListForStation: 的个人内部调用中捕获错误。

- (RACSignal *)processStationList
{
    NSArray *urlList = @[@"http://66.55.93.205/listen.pls",@"http://84.20.77.50:8000/listen.pls",@"http://valekalter.serverroom.us:9264/listen.pls", @"http://66.55.93.205:8080/listen.pls"];

    return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        [[[urlList.rac_sequence.signal flattenMap:^RACStream *(NSString *urlString) {
            NSLog(@"flatten map %@",urlString);
            return [[self fetchStationURLListForStation:urlString]
                   catch:^RACSignal *(NSError *error) {
                       NSLog(@"catch %@",error);
                       return [RACSignal empty];
                   }];
        }]
        subscribeNext:^(id x) {
            NSLog(@"subscribe next %@",x);
        }];
        return nil;
    }];
}

另外,请确保不要在您的块中引用self。使用 @weakify@strongify 宏,或使用在 return 语句上方声明的对 self 的弱引用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-11-03
    • 2013-09-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-03
    相关资源
    最近更新 更多