Combine sink: ignore receiveValue, only completion is needed(合并接收器:忽略ReceiveValue,只需要完成)
问题描述
考虑以下代码:
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
}
只需查看CurrentValueSubject
初始值设定项,就可以清楚地看到该值不是必需的/无关紧要。
我正在使用此特定发布服务器发出一个可以通过也可以失败的异步网络请求。
由于我对此发布者返回的值不感兴趣(没有),我如何摆脱receiveValue
闭包?
理想情况下,调用站点代码应如下所示:
CurrentValueSubject<Void, Error>(())
.eraseToAnyPublisher()
.sink { completion in
switch completion {
case .failure(let error):
print(error)
print("FAILURE")
case .finished:
print("SUCCESS ")
}
}
也可能是我应该使用AnyPublisher
以外的其他内容,因此,如果API更适合您的目的,请随时建议/重写它。
我所能找到的最接近的解决方案是ignoreOutput,但它仍然返回值。
推荐答案
CurrentValueSubject
似乎是一个令人困惑的选择,因为这将在您第一次订阅它时发送初始值(Void
)。
您可以使用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")
}
}
您正在用链的一端的丑陋代码替换另一端的丑陋代码,但如果这隐藏在AnyPublisher
后面,并且您关心正确的用法,那么这似乎是正确的方法。消费者可以通过查看输出和错误类型准确地看到预期的结果,而不必在单独的闭包中处理它们。
这篇关于合并接收器:忽略ReceiveValue,只需要完成的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!