32

在 ReactiveCocoa 中,如果我们链接多个依赖信号,我们必须使用subscribeNext:链中的下一个信号来接收前一个信号产生的值(例如,异步操作的结果)。所以过了一会儿,代码变成了这样(省略了不必要的细节):

RACSignal *buttonClickSignal = [self.logIn rac_signalForControlEvents:UIControlEventTouchUpInside];

[buttonClickSignal subscribeNext:^(UIButton *sender) {    // signal from a button click
    // prepare data

    RACSignal *loginSignal = [self logInWithUsername:username password:password];    // signal from the async network operation

    [loginSignal subscribeNext:^void (NSDictionary *json) {
        // do stuff with data received from the first network interaction, prepare some new data

        RACSignal *playlistFetchSignal = [self fetchPlaylistForToken:token];         // another signal from the async network operation

        [playlistFetchSignal subscribeNext:^(NSDictionary *json) {
            // do more stuff with the returned data
        }];

        // etc
    }];
}];

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

[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 中是否有更好的链接依赖工作的模式?

4

1 回答 1

48

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

[[[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:or-sequenceNext:代替以获得类似的效果(但为了更清晰地表达意图)。

于 2013-04-05T06:35:38.717 回答