Ric*_*hiy 8 reactive-programming swift swiftui combine
考虑以下代码:
CurrentValueSubject<Void, Error>(())
.eraseToAnyPublisher()
.sink { completion in
switch completion {
case .failure(let error):
print(error)
print("FAILURE")
case .finished:
print("SUCCESS")
}
} receiveValue: { value in
// this should be ignored
}
Run Code Online (Sandbox Code Playgroud)
只需查看CurrentValueSubject初始值设定项,就可以清楚地看出该值不需要/无关紧要。
我正在使用这个特定的发布者发出异步网络请求,该请求可能会通过也可能会失败。
由于我对此发布者返回的值不感兴趣(没有),我怎样才能摆脱闭receiveValue包?
理想情况下,调用站点代码应如下所示:
CurrentValueSubject<Void, Error>(())
.eraseToAnyPublisher()
.sink { completion in
switch completion {
case .failure(let error):
print(error)
print("FAILURE")
case .finished:
print("SUCCESS ")
}
}
Run Code Online (Sandbox Code Playgroud)
也可能是我应该使用不同于 的东西AnyPublisher,所以如果它更适合目的,请随意提议/重写 API。
我能找到的最接近的解决方案是ignoreOutput,但它仍然返回一个值。
您只需完成即可声明另一个接收器:
extension CurrentValueSubject where Output == Void {
func sink(receiveCompletion: @escaping ((Subscribers.Completion<Failure>) -> Void)) -> AnyCancellable {
sink(receiveCompletion: receiveCompletion, receiveValue: {})
}
}
Run Code Online (Sandbox Code Playgroud)
CurrentValueSubjectVoid似乎是一个令人困惑的选择,因为当您第一次订阅它时,它会发送一个初始值( )。
您可以通过使用 使事情变得不那么模糊Future,完成后它将发送唯一一个值。
为了避免接收您不关心的值,您可以翻转情况并使用输出类型Result<Void, Error>和 失败类型Never。.failure(error)当处理您的网络请求时,您可以使用或履行承诺.success(()),并在接收器中处理它:
let pub = Future<Result<Void, Error>, Never> {
promise in
// Do something asynchronous
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
promise(.success(.success(())))
//or
//promise(.success(.failure(error)))
}
}.eraseToAnyPublisher()
// somewhere else...
pub.sink {
switch $0 {
case .failure(let error):
print("Whoops \(error)")
case .success:
print("Yay")
}
}
Run Code Online (Sandbox Code Playgroud)
您将链一端的丑陋代码替换为另一端的丑陋代码,但如果它被隐藏在后面AnyPublisher并且您关心正确的使用,那么这似乎是正确的方法。消费者可以通过查看输出和错误类型准确地看到预期的结果,而不必在单独的闭包中处理它们。
| 归档时间: |
|
| 查看次数: |
6409 次 |
| 最近记录: |