我想每 60 分钟调用一次基于计时器发布者的 URLSession 发布者。
这似乎应该是可能的,但不知道如何去做:
例如;
Client
答案 0 :(得分:0)
class MyClass: ObservableObject {
@Published var response: Response? = nil
var cancelable : AnyCancellable?
func connectPoller() {
let timer = Timer.TimerPublisher(interval: 60 * 60, runLoop: .main, mode: .default)
.autoconnect() //<= here
cancelable = timer
.flatMap { _ in
URLSession.shared.dataTaskPublisher(for: URL(string: "some-url-here")!).tryMap() { element -> Data in
guard let httpResponse = element.response as? HTTPURLResponse,
httpResponse.statusCode == 200 else {
throw URLError(.badServerResponse)
}
return element.data
}
.decode(type: Response?.self, decoder: JSONDecoder()).eraseToAnyPublisher()
.replaceError(with: nil)
}
.receive(on: RunLoop.main) //<= here
.assign(to: \.response, on: self)
}
}
答案 1 :(得分:0)
为了将 Timer 发布者转换为 URLSession dataTask 发布者,您需要使用 flatMap
。此外,您需要确保发布者链无法完成,因为计时器将在此时停止触发。因此,您需要对 flatMap
中的错误进行更积极的清理,以免它们进一步向下传播。
class MyClass: ObservableObject {
@Published var response: Response? = nil
var cancellable : AnyCancellable?
func connectPoller() {
cancellable = Timer.publish(every: 5, on: .main, in: .default)
.autoconnect()
.flatMap { _ in
URLSession.shared.dataTaskPublisher(for: URL(string: "https://google.com")!)
.flatMap { element -> AnyPublisher<Data,Never> in
guard let httpResponse = element.response as? HTTPURLResponse,
httpResponse.statusCode == 200 else {
return Just(Data()).eraseToAnyPublisher()
}
return Just(element.data).eraseToAnyPublisher()
}
.decode(type: Response?.self, decoder: JSONDecoder())
.replaceError(with: nil)
}
.print()
.receive(on: RunLoop.main)
.assign(to: \.response, on: self)
}
}