我想每隔60分钟调用一个基于计时器发布器的URLSession发布器。
看起来这应该是可能的,但不知道该怎么做:
例如:
struct Response: Codable {
// ... some fields here
}
class MyClass: ObservableObject {
@Published var response: Response? = nil
var cancelable : AnyCancelable?
func connectPoller() {
let timer = Timer.TimerPublisher(interval: 60 * 60, runLoop: .main, mode: .default)
// how to chain this?
// want to connect the timer to invoke the data task
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).assign(to: \.response, on: self)
}
}
发布于 2021-06-14 23:33:51
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)
}
}
发布于 2021-06-14 23:37:18
为了将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)
}
}
https://stackoverflow.com/questions/67970269
复制相似问题