ReactiveCocoa catch all the errors - async network operation on collection object

jpsasi

I have just started learning reactivecocoa. i want to perform network operation for each entry in a collection object and parse return result, mark the entry as invalid if an error is reported.

The following example illustrate the problem. urlList array is having 4 entries.2 entries generates error (generates connection closed and timeout error). so subscribe block is not notified for all the entries.

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

Output:

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."}

I want subscribeNext/Error block to be notified for all the entries in the collection,so that i can mark the entry as valid or invalid.

How to achieve it using reactive cocoa.

UPDATE

I have tried with replacing the subscription block with catch block like below. it catches only the first error event.

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

Output:

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."}

How to catch all the errors?

drhr

When your -fetchStationURLListForStation: function calls -sendError: on its subscriber(s), it also ends the signal. The outermost subscriber here catches the error, so the entire outer signal ends as well.

One possibility is to catch errors on your individual inner calls to -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;
    }];
}

Also, be sure not to reference self within your blocks. Use the @weakify and @strongify macros, or use a weak reference to self that you declare above the return statement.

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

如何使用try / catch在Async / Await函数中使用Promise.all

来自分类Dev

Catching all errors

来自分类Dev

如何正确使用 try/catch、promise catch 和 async 函数?

来自分类Dev

F#继续执行Async.Catch

来自分类Dev

F#继续执行Async.Catch

来自分类Dev

从对象创建Collection <object>

来自分类Dev

How to cast list collection to derived collection object?

来自分类Dev

How do I catch all of these exceptions in python?

来自分类Dev

节点:使用嵌套的 async/await try/catch 冒泡错误响应

来自分类Dev

数组列表到Collection <Object>

来自分类Dev

undefined object in map collection javascript

来自分类Dev

在catch块JS中创建新的Object()

来自分类Dev

在iOS中将ReactiveCocoa与非MVVM / ReactiveCocoa结合

来自分类Dev

Dagger + Proguard obfuscation, Errors creating object graph

来自分类Dev

Error: "Operation is not valid due to the current state of the object"

来自分类常见问题

Why shouldn't all functions be async by default?

来自分类Dev

map()与async vs promise.all()

来自分类Dev

带有MVVM的ReactiveCocoa

来自分类Dev

UISearchResultsUpdating w / ReactiveCocoa

来自分类Dev

ReactiveCocoa中的内存管理

来自分类Dev

Alamofire 3.0 ReactiveCocoa转换

来自分类Dev

UITextFieldDelegate带ReactiveCocoa的textFieldShouldReturn

来自分类Dev

使用ReactiveCocoa查看验证

来自分类Dev

将Set <Object>转换为Collection <String>

来自分类Dev

休眠:如何注释Collection <Object>以允许搜索

来自分类Dev

访问以Collection <Object>类型返回的ArrayList

来自分类Dev

在 Promise.all catch 中访问 jQuery ajax 错误

来自分类Dev

Flask-restful 中的 Catch-All URL 示例也捕获 /

来自分类Dev

nodejs async/await try/catch 在不应该通过的时候测试通过

Related 相关文章

热门标签

归档