And*_*ndi 8 objective-c reactive-cocoa
我有两个网络信号,我想合并,但有一些限制.
让我们调用网络信号A和B.A确实使用AFNetworking在缓存中查找资源并立即返回该请求的任何响应.B还会考虑缓存,但可以转到远程服务器以重新验证响应.
好的,我想做的是:
要求A:
要求B:
我目前的解决方案是:
- (RACSignal *)issueById:(NSString *)issueId {
RACSignal *filterSignal = [RACSignal createSignal:^RACDisposable *(id <RACSubscriber> subscriber) {
RACSignal *cacheSignal = [[IssueWSRequest instance] issueWithId:issueId cachePolicy:NSURLRequestReturnCacheDataDontLoad];
return [cacheSignal subscribeNext:^(id x) {
[subscriber sendNext:x];
} error:^(NSError *error) {
NSLog(@"Ignore error");
[subscriber sendCompleted];
} completed:^{
[subscriber sendCompleted];
}];
}];
RACSignal *remoteSignal = [[IssueWSRequest instance] issueWithId:issueId cachePolicy:NSURLRequestUseProtocolCachePolicy];
RACSignal *combined = [RACSignal merge:@[newSign, remoteSignal]];
return combined;
}
Run Code Online (Sandbox Code Playgroud)
我知道这个解决方案不符合我的要求,所以我想知道是否有人可以帮助我找到更好的解决方案.
- (RACSignal *)issueById:(NSString *)issueId {
RACSubject *localErrors = [RACSubject subject];
RACSignal *remoteSignal = [[IssueWSRequest instance] issueWithId:issueId cachePolicy:NSURLRequestUseProtocolCachePolicy];
RACSignal *cacheSignal = [[[[[[IssueWSRequest instance] issueWithId:issueId cachePolicy:NSURLRequestReturnCacheDataDontLoad]
takeUntil:remoteSignal] doError:^(NSError *error) {
[localErrors sendNext:error];
}] finally:^{
// Make sure to complete the subject, since infinite signals are
// difficult to use.
[localErrors sendCompleted];
}]
replayLazily];
return [RACSignal merge:@[
[cacheSignal catchTo:[RACSignal empty]],
remoteSignal
]];
}
Run Code Online (Sandbox Code Playgroud)
Jus*_*ers 12
这是一个很难回答的问题,因为您所需的错误处理从根本上与RACSignalAPI契约不兼容,后者声明错误具有异常语义.
忽略但仍然关心错误的唯一方法是将它们重定向到其他地方.在这个例子中,我将使用一个主题:
RACSubject *remoteErrors = [RACSubject subject];
Run Code Online (Sandbox Code Playgroud)
...但您也可以使用属性或其他通知机制.
我将继续使用remoteSignal与cacheSignal您在上面给出了一些修改.这是我们想要的行为:
remoteSignal 应该发送错误 remoteErrorscacheSignal应该在remoteSignal发送值后立即取消cacheSignal和的值remoteSignal,以便在读取缓存后仍然获取远程值考虑到这一点,让我们来看看remoteSignal:
RACSignal *remoteSignal = [[[[[IssueWSRequest
instance]
issueWithId:issueId cachePolicy:NSURLRequestUseProtocolCachePolicy]
doError:^(NSError *error) {
[remoteErrors sendNext:error];
}]
finally:^{
// Make sure to complete the subject, since infinite signals are
// difficult to use.
[remoteErrors sendCompleted];
}]
replayLazily];
Run Code Online (Sandbox Code Playgroud)
在-doError:与-finally:控制remoteErrors问题,实现我们上面的第一个要求.因为我们需要remoteSignal在多个地方使用(你可以在上面的列表中看到),我们用它-replayLazily来确保它的副作用只发生一次.
cacheSignal几乎没有变化.我们只需要使用-takeUntil:它来确保它在remoteSignal发送值时终止(但如果它发送错误则不会终止):
RACSignal *cacheSignal = [[[IssueWSRequest
instance]
issueWithId:issueId cachePolicy:NSURLRequestReturnCacheDataDontLoad]
takeUntil:remoteSignal];
Run Code Online (Sandbox Code Playgroud)
最后,我们想要合并它们的值,以便两个信号同时启动,它们的值可以按任何顺序到达:
return [RACSignal merge:@[
[cacheSignal catchTo:[RACSignal empty]],
[remoteSignal catchTo:[RACSignal empty]]
];
Run Code Online (Sandbox Code Playgroud)
我们在这里忽略了错误,因为任何一个错误都会终止(因为它们现在已经合并).我们的错误处理行为已经在上面处理了.
并且,尽管合并,使用-takeUntil:on cacheSignal确保它不可能在之后发送值remoteSignal.
再看一下需求列表,您可以看到用于实现每个需求的运算符:
[-doError:] remoteSignal 应该发送错误 remoteErrors[-takeUntil:] cacheSignal应该在remoteSignal发送值后立即取消[-catchTo:] 任何一个信号的错误都不应该终止另一个[+merge:]我们希望合并来自cacheSignal和的值remoteSignal,以便在读取缓存后仍然获取远程值| 归档时间: |
|
| 查看次数: |
2953 次 |
| 最近记录: |