使用 RxSwift 每 10 秒进行一次网络调用
Make a network call every 10 seconds with RxSwift
我对 RxSwift 完全陌生。我设法加载了我的 table 视图,但现在我想每 10 秒打一次电话。
我正在阅读 我可能应该使用 Observable<Int>.interval(10, scheduler: MainScheduler.instance)
,我试过但没有成功。
class MarketService: MarketServiceProtocol {
func fetchMarkets() -> Observable <[Market]> {
return Observable.create { observer -> Disposable in
RestManager.shared.makeRequest(withEndPoint: "market/v2/get-summary?region=US" , withHttpMethod: .get) { result in
if let error = result.error {
observer.onError(error)
return
}
guard let response = result.response,
200 ... 299 ~= response.httpStatusCode else {
return
}
guard let data = result.data else {
return
}
do {
let decodedData = try JSONDecoder().decode(MarketResult.self, from: data)
observer.onNext(decodedData.marketSummaryAndSparkResponse.markets)
} catch {
observer.onError(error)
}
}
return Disposables.create { }
}
}
}
然后我调用我的视图控制器:
viewModel.fetchMarketViewModels().observe(on: MainScheduler.instance).bind(to: tableView.rx.items(cellIdentifier: HomeTableViewCell.cellIdentifier)) {
index, viewModel, cell in
guard let cell = cell as? HomeTableViewCell else { return }
cell.setupData(viewModel: viewModel)
}.disposed(by: self.disposableBag)
您的 Observable.create 关闭有几个问题。您必须确保在每个路径中都将某些内容发送到 observer
,否则 Observable 将调用该函数然后不发出任何内容,您将不知道为什么。
此外,您还想尽量减少在传递给 create 的闭包中执行的逻辑量。你在那里做的太多了。
所以我们先把create闭包中的代码尽量简化一下:
extension RestManager {
func rx_makeRequest(withEndPoint endPoint: String, withHttpMethod method: HttpMethod) -> Observable<(response: MyHTTPURLResponse, data: Data)> {
Observable.create { observer in
self.makeRequest(withEndPoint: endPoint, withHttpMethod: method) { result in
if let response = result.response, let data = result.data {
observer.onNext((response, data))
observer.onCompleted()
}
else {
observer.onError(result.error ?? RxError.unknown)
}
}
return Disposables.create() // is there some way of canceling a request? If so, it should be done here.
}
}
}
这是最低要求。仅包装底层回调,仅此而已。现在您的 fetchMarkets
调用更简单了:
class MarketService: MarketServiceProtocol {
func fetchMarkets() -> Observable <[Market]> {
return RestManager.shared.rx_makeRequest(withEndPoint: "market/v2/get-summary?region=US", withHttpMethod: .get)
.do(onNext: { result in
guard 200...299 ~= result.response.httpStatusCode
else { throw URLError.httpRequestFailed(response: result.response, data: result.data) }
})
.map { try JSONDecoder().decode(MarketResult.self, from: [=11=].data).marketSummaryAndSparkResponse.markets }
}
}
现在谈谈你的问题。如何每 10 秒进行一次网络调用...只需将您的网络调用包装在一个 flatMap 中,如下所示:
Observable<Int>.interval(.seconds(10), scheduler: MainScheduler.instance)
.flatMapLatest { _ in
viewModel.fetchMarketViewModels()
}
.observe(on: MainScheduler.instance)
.bind(to: tableView.rx.items(cellIdentifier: HomeTableViewCell.cellIdentifier)) { index, viewModel, cell in
guard let cell = cell as? HomeTableViewCell else { return }
cell.setupData(viewModel: viewModel)
}
.disposed(by: self.disposableBag)
从 this article 中了解有关 flatMap
及其变体的更多信息。
我对 RxSwift 完全陌生。我设法加载了我的 table 视图,但现在我想每 10 秒打一次电话。
我正在阅读 Observable<Int>.interval(10, scheduler: MainScheduler.instance)
,我试过但没有成功。
class MarketService: MarketServiceProtocol {
func fetchMarkets() -> Observable <[Market]> {
return Observable.create { observer -> Disposable in
RestManager.shared.makeRequest(withEndPoint: "market/v2/get-summary?region=US" , withHttpMethod: .get) { result in
if let error = result.error {
observer.onError(error)
return
}
guard let response = result.response,
200 ... 299 ~= response.httpStatusCode else {
return
}
guard let data = result.data else {
return
}
do {
let decodedData = try JSONDecoder().decode(MarketResult.self, from: data)
observer.onNext(decodedData.marketSummaryAndSparkResponse.markets)
} catch {
observer.onError(error)
}
}
return Disposables.create { }
}
}
}
然后我调用我的视图控制器:
viewModel.fetchMarketViewModels().observe(on: MainScheduler.instance).bind(to: tableView.rx.items(cellIdentifier: HomeTableViewCell.cellIdentifier)) {
index, viewModel, cell in
guard let cell = cell as? HomeTableViewCell else { return }
cell.setupData(viewModel: viewModel)
}.disposed(by: self.disposableBag)
您的 Observable.create 关闭有几个问题。您必须确保在每个路径中都将某些内容发送到 observer
,否则 Observable 将调用该函数然后不发出任何内容,您将不知道为什么。
此外,您还想尽量减少在传递给 create 的闭包中执行的逻辑量。你在那里做的太多了。
所以我们先把create闭包中的代码尽量简化一下:
extension RestManager {
func rx_makeRequest(withEndPoint endPoint: String, withHttpMethod method: HttpMethod) -> Observable<(response: MyHTTPURLResponse, data: Data)> {
Observable.create { observer in
self.makeRequest(withEndPoint: endPoint, withHttpMethod: method) { result in
if let response = result.response, let data = result.data {
observer.onNext((response, data))
observer.onCompleted()
}
else {
observer.onError(result.error ?? RxError.unknown)
}
}
return Disposables.create() // is there some way of canceling a request? If so, it should be done here.
}
}
}
这是最低要求。仅包装底层回调,仅此而已。现在您的 fetchMarkets
调用更简单了:
class MarketService: MarketServiceProtocol {
func fetchMarkets() -> Observable <[Market]> {
return RestManager.shared.rx_makeRequest(withEndPoint: "market/v2/get-summary?region=US", withHttpMethod: .get)
.do(onNext: { result in
guard 200...299 ~= result.response.httpStatusCode
else { throw URLError.httpRequestFailed(response: result.response, data: result.data) }
})
.map { try JSONDecoder().decode(MarketResult.self, from: [=11=].data).marketSummaryAndSparkResponse.markets }
}
}
现在谈谈你的问题。如何每 10 秒进行一次网络调用...只需将您的网络调用包装在一个 flatMap 中,如下所示:
Observable<Int>.interval(.seconds(10), scheduler: MainScheduler.instance)
.flatMapLatest { _ in
viewModel.fetchMarketViewModels()
}
.observe(on: MainScheduler.instance)
.bind(to: tableView.rx.items(cellIdentifier: HomeTableViewCell.cellIdentifier)) { index, viewModel, cell in
guard let cell = cell as? HomeTableViewCell else { return }
cell.setupData(viewModel: viewModel)
}
.disposed(by: self.disposableBag)
从 this article 中了解有关 flatMap
及其变体的更多信息。