【问题标题】:Chaining dependent signals in ReactiveCocoa在 ReactiveCocoa 中链接依赖信号
【发布时间】:2013-04-05 14:35:38
【问题描述】:

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

【问题讨论】:

    标签: ios objective-c reactive-programming reactive-cocoa


    【解决方案1】:

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

    【讨论】:

    • 这个解决方案对我有用。我写了一个blog article,更详细地解释了这种方法。
    • @Justin,您介意详细说明在此过程中进行错误处理的正确方法吗?
    • @DogpatchTech 您可以为此使用-catch:-catchTo:。见this explanation
    • -sequenceMany:-sequenceNext: 在 2.0+ 中已弃用; -sequenceMany: 应该被替换为 -flattenMap: 而忽略块参数; -sequenceNext: 替换为 -then:。 (请参阅此处的更改日志条目:github.com/ReactiveCocoa/ReactiveCocoa/blob/master/…
    • @ValerioSantinelli 像 -then:-materialize 或类似的运算符。不过,这听起来像是代码异味。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-10-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-14
    • 2014-05-23
    相关资源
    最近更新 更多