gpt4 book ai didi

swift - 链式网络请求 RXSwift

转载 作者:行者123 更新时间:2023-12-04 07:55:00 32 4
gpt4 key购买 nike

嘿,我在 HackingWithSwift 教程中学到了如何使用 Combine 发出链接的网络请求(请参阅下面的代码)。现在我将使用 RXSwift 构建相同的逻辑,但我不知道如何像在 Combine 中一样获取/订阅以获得最终结果。
结合:

//Combine code
func fetch<T: Decodable>(_ url: URL, defaultValue: T) -> AnyPublisher<T, Never> {
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .iso8601

return URLSession.shared.dataTaskPublisher(for: url)
.retry(1)
.map(\.data)
.decode(type: T.self, decoder: decoder)
.replaceError(with: defaultValue)
.receive(on: DispatchQueue.main)
.eraseToAnyPublisher()
}

//call fetch method and get the end result
fetch(url, defaultValue: [URL]())
.flatMap { urls in
urls.publisher.flatMap { url in
fetch(url, defaultValue: [NewsItem]())
}
}
.collect()
.sink { values in
let allItems = values.joined()
items = allItems.sorted { $0.id > $1.id }
}
.store(in: &requests)



//RXSwift code
func fetchWithRX<T: Decodable>(_ url: URL, defaultValue: T) -> Observable<T> {
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .iso8601
let request = URLRequest(url: url)

return URLSession.shared.rx.response(request: request)
.retry(1)
.map(\.data)
.decode(type: T.self, decoder: decoder)
.debug()
.catchAndReturn(defaultValue)
.observe(on: MainScheduler.instance)
}


//call fetch2 method
Now I want to subscribe to the values like in the first fetch method with flatMap..collect..sink etc.

fetchWithRX(url, defaultValue: [URL]())

最佳答案

我会这样写模拟:

fetchWithRX(url, defaultValue: [URL]())
.flatMap { urls in
Observable.zip(urls.map { fetchWithRX($0, defaultValue: [NewsItem]()) })
}
.map { $0.flatMap { $0 }.sorted { $0.id > $1.id } }
.subscribe(onNext: { values in
items = values
})
.disposed(by: requests)
这样,我将所有逻辑移动到 map可以将闭包移到函数中以实现可测试性。最小化 flatMap 中的代码量或 subscribe以提高代码的可测试性。
或者你可以这样写:
fetchWithRX(url, defaultValue: [URL]())
.flatMap { urls in
Observable.zip(urls.map { fetchWithRX($0, defaultValue: [NewsItem]()) })
}
.subscribe(onNext: { values in
let allItems = values.joined()
items = allItems.sorted { $0.id > $1.id }
})
.disposed(by: requests)
你可以在这篇文章中了解更多关于组合观察的信息: Recipes for Combining Observables in RxSwift
URLSession 还有一个操作符 data(request:)它只会发出数据,因此您不必映射以转储结果对象。像这样:
func fetchWithRX<T: Decodable>(_ url: URL, defaultValue: T) -> Observable<T> {
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .iso8601
return URLSession.shared.rx.data(request: URLRequest(url: url))
.retry(1)
.decode(type: T.self, decoder: decoder)
.catchAndReturn(defaultValue)
.observe(on: MainScheduler.instance)
}
我突然想到,您可能正在寻找原始组合代码的直接推论……上述示例将具有相同的最终输出,但它们的工作方式略有不同……
这是直接翻译:
fetchWithRX(url, defaultValue: [URL]())
.flatMap { urls in
// Observable.from(urls) works like urls.publisher
Observable.from(urls).flatMap { url in
fetchWithRX(url, defaultValue: [NewsItem]())
}
}
.toArray() // works like collect(). However, toArray() returns a Single rather than a generic Observable.
.subscribe(onSuccess: { values in
let allItems = values.joined()
items = allItems.sorted { $0.id > $1.id }
})
.disposed(by: requests)
不同之处在于其他示例保留了新闻项的顺序,而这没有。由于您无论如何都在收集和排序,因此最终输出是相同的。如果您不使用 collect(),您只会看到不同之处。/ toArray()在观察输出之前。

关于swift - 链式网络请求 RXSwift,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66747996/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com