Ios ReactiveCocoa中的链式依赖信号

Ios ReactiveCocoa中的链式依赖信号,ios,objective-c,reactive-programming,reactive-cocoa,Ios,Objective C,Reactive Programming,Reactive Cocoa,在ReactiveCocoa中,如果我们链接多个相关信号,则必须使用链中的下一个信号的subscribeNext:,以接收上一个信号生成的值(例如,异步操作的结果)。因此,过了一段时间,代码会变成这样(省略了不必要的细节): 这种不断增加的嵌套看起来并不比文档中给出的非反应性示例好多少: [client logInWithSuccess:^{ [client loadCachedMessagesWithSuccess:^(NSArray *messages) { [cli

在ReactiveCocoa中,如果我们链接多个相关信号,则必须使用链中的下一个信号的
subscribeNext:
,以接收上一个信号生成的值(例如,异步操作的结果)。因此,过了一段时间,代码会变成这样(省略了不必要的细节):

这种不断增加的嵌套看起来并不比文档中给出的非反应性示例好多少:

[client logInWithSuccess:^{
    [client loadCachedMessagesWithSuccess:^(NSArray *messages) {
        [client fetchMessagesAfterMessage:messages.lastObject success:^(NSArray *nextMessages) {
            NSLog(@"Fetched all messages.");
        } failure:^(NSError *error) {
            [self presentError:error];
        }];
    } failure:^(NSError *error) {
        [self presentError:error];
    }];
} failure:^(NSError *error) {
    [self presentError:error];
}];
我错过什么了吗?在ReactiveCocoa中是否有更好的链接依赖性工作模式?

这是and运算符开始真正派上用场的时候。在您的特定示例中,您可以使用
-flattmap:
将结果合并到新信号中:

[[[buttonClickSignal
    flattenMap:^(UIButton *sender) {
        // prepare 'username' and 'password'
        return [self logInWithUsername:username password:password];
    }]
    flattenMap:^(NSDictionary *json) {
        // prepare 'token'
        return [self fetchPlaylistForToken:token];
    }]
    subscribeNext:^(NSDictionary *json) {
        // do stuff with the returned playlist data
    }];

如果您不需要任何步骤的结果,您可以使用
-sequenceMany:
-sequenceNext:
来获得类似的效果(但为了更清晰地表达意图)。

这个解决方案对我很有效。我写了一篇文章,更详细地解释了这种方法。@Justin,你介意详细阐述一下如何正确处理错误吗?@DogpatchTech你可以使用
-catch:
-catchTo:
。请参阅。
-sequenceMany:
-sequenceNext:
在2.0+中被弃用
-sequenceMany:
应替换为
-flattmap:
,同时忽略块参数<代码>-sequenceNext:替换为
-然后:
。(参见此处的changelog条目:)@ValerioSantinelli一个类似于
-then:
,或
-materialize
之类的操作符。不过,这听起来像是一种代码气味。
[[[buttonClickSignal
    flattenMap:^(UIButton *sender) {
        // prepare 'username' and 'password'
        return [self logInWithUsername:username password:password];
    }]
    flattenMap:^(NSDictionary *json) {
        // prepare 'token'
        return [self fetchPlaylistForToken:token];
    }]
    subscribeNext:^(NSDictionary *json) {
        // do stuff with the returned playlist data
    }];