我正在使用缓存重放信号的典型模式:

- (RACSignal *)resultSignal {
    if (!_resultSignal) {
        _resultSignal = [self createResultSignal];
    }

    return _resultSignal;
}

- (RACSignal *)createResultSignal {
    return [[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        [someObject doWorkWithCompletionBlock:^(id result) {
            [subscriber sendNext:result];
            [subscriber sendCompleted];
        }
                                failure:^(NSError *error) {
            [subscriber sendError:error];
        }];

        return nil;
    }] replay];
}

这很好用,但是现在我想添加一个在工作失败时重试的功能。我可以使用-[RACSignal retry]-[RACSignal retry:],但这不会立即将错误通知订阅者。相反,我想要的是让该信号的现有订阅者获取错误,但随后对-resultSignal的调用将接收新信号,或重试现有信号。

我可以对该信号进行-catch:并在块中将_resultSignal设置为nil,但随后我将不得不担心比赛条件,而且我认为这不是“反应性”的方式。

什么是实现此行为的适当方式?

更新:

感谢@joshaber!我最终采用了建议的方法,但我认为这还不错:
- (RACSignal *)resultSignal {
    @synchronized(_resultSignal) {
        if (!_resultSignal) {
            @weakify(self);

            _resultSignal = [[self createResultSignal] catch:^RACSignal *(NSError *error) {
                @strongify(self);

                self.resultSignal = nil;
                return [RACSignal error:error];
            }];
        }

        return _resultSignal;
    }
}

- (void)setResultSignal:(RACSignal *)signal {
    @synchronized(_resultSignal) {
        _resultSignal = signal;
    }
}

最佳答案

我已经考虑了一段时间了。如果我希望我能得到一个很好的答案,是否有帮助? ;)

我可以-catch:该信号并将_resultSignal设置为nil,但随后我将不得不担心竞争状况,而且我认为这不是“反应性”的方法。

这就是我的目标。

或者,您可以使用信号信号。它会发送最新的信号。现有订户将被订阅旧信号,而新订户将获得重试信号。但这可能需要手动使用RACSubject,因此与其他解决方案相比,我不知道额外的复杂性值得。

关于ios - 使信号仅重试新订户,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/22160662/

10-09 15:02
查看更多