Swift。结合。重试时有没有办法多次调用发布者块?
Swift. Combine. Is there any way to call a publisher block more than once when retry?
我想在使用 Swift/Combine 中的 retry() 发生某些错误时多次发出网络请求。发布者内部的块仅被调用一次,这意味着当发生错误时,只会对真实应用程序发出一次请求。我的代码是:
import UIKit
import Combine
import PlaygroundSupport
enum TestFailureCondition: Error {
case invalidServerResponse
}
var backgroundQueue: DispatchQueue = DispatchQueue(label: "backgroundQueue")
var failPublisher: AnyPublisher<(Data, URLResponse), Error> {
Future<(Data, URLResponse), Error> { promise in
print("Attempt to call")
backgroundQueue.asyncAfter(deadline: .now() + Double.random(in: 1..<3)) {
promise(.failure(TestFailureCondition.invalidServerResponse))
}
}
.eraseToAnyPublisher()
}
let cancellable = failPublisher
.print("(1)>")
.retry(3)
.print("(2)>")
.sink(receiveCompletion: { fini in
print(" ** .sink() received the completion:", String(describing: fini))
PlaygroundPage.current.finishExecution()
}, receiveValue: { stringValue in
print(" ** .sink() received \(stringValue)")
})
PlaygroundPage.current.needsIndefiniteExecution = true
我希望 backgroundQueue.asyncAfter(deadline)
在发生某些错误之前被调用三次。有谁知道为什么?
我设法通过使用 tryCatch()
函数并发出另一个请求来实现预期的行为:Link
link 包含两种实现相同行为的方法,包括上面提到的 Deferred {}
。
Future
运行一旦创建它的主体,即使没有订阅它。它保存结果并以相同的结果完成所有订阅。因此,在 Future
上使用 retry
运算符不会使 Future
运行 在失败时再次成为它的主体。
您希望每个人再次订阅 运行 正文。您可以通过将 Future
包装在 Deferred
中来实现。 Deferred
将为每个订阅创建一个新的 Future
。
var failPublisher: AnyPublisher<(Data, URLResponse), Error> {
Deferred {
Future<(Data, URLResponse), Error> { promise in
print("Attempt to call")
backgroundQueue.asyncAfter(deadline: .now() + Double.random(in: 1..<3)) {
promise(.failure(TestFailureCondition.invalidServerResponse))
}
}
}
.eraseToAnyPublisher()
}
我想在使用 Swift/Combine 中的 retry() 发生某些错误时多次发出网络请求。发布者内部的块仅被调用一次,这意味着当发生错误时,只会对真实应用程序发出一次请求。我的代码是:
import UIKit
import Combine
import PlaygroundSupport
enum TestFailureCondition: Error {
case invalidServerResponse
}
var backgroundQueue: DispatchQueue = DispatchQueue(label: "backgroundQueue")
var failPublisher: AnyPublisher<(Data, URLResponse), Error> {
Future<(Data, URLResponse), Error> { promise in
print("Attempt to call")
backgroundQueue.asyncAfter(deadline: .now() + Double.random(in: 1..<3)) {
promise(.failure(TestFailureCondition.invalidServerResponse))
}
}
.eraseToAnyPublisher()
}
let cancellable = failPublisher
.print("(1)>")
.retry(3)
.print("(2)>")
.sink(receiveCompletion: { fini in
print(" ** .sink() received the completion:", String(describing: fini))
PlaygroundPage.current.finishExecution()
}, receiveValue: { stringValue in
print(" ** .sink() received \(stringValue)")
})
PlaygroundPage.current.needsIndefiniteExecution = true
我希望 backgroundQueue.asyncAfter(deadline)
在发生某些错误之前被调用三次。有谁知道为什么?
我设法通过使用 tryCatch()
函数并发出另一个请求来实现预期的行为:Link
link 包含两种实现相同行为的方法,包括上面提到的 Deferred {}
。
Future
运行一旦创建它的主体,即使没有订阅它。它保存结果并以相同的结果完成所有订阅。因此,在 Future
上使用 retry
运算符不会使 Future
运行 在失败时再次成为它的主体。
您希望每个人再次订阅 运行 正文。您可以通过将 Future
包装在 Deferred
中来实现。 Deferred
将为每个订阅创建一个新的 Future
。
var failPublisher: AnyPublisher<(Data, URLResponse), Error> {
Deferred {
Future<(Data, URLResponse), Error> { promise in
print("Attempt to call")
backgroundQueue.asyncAfter(deadline: .now() + Double.random(in: 1..<3)) {
promise(.failure(TestFailureCondition.invalidServerResponse))
}
}
}
.eraseToAnyPublisher()
}