RxSwift,依赖链的下载返回相同的 Observable 类型
Posted
技术标签:
【中文标题】RxSwift,依赖链的下载返回相同的 Observable 类型【英文标题】:RxSwift, chain dependent downloads returning same Observable type 【发布时间】:2018-04-27 12:57:41 【问题描述】:我正在从 API 下载书籍列表,并且我想为每本书下载封面图片。
我坚持认为这是 Rx 中非常简单和常见的任务。我已经进行了研究,但找不到解决方案,因为所有相关问题都是关于如何返回另一个Observable
;例如获取 Github 存储库,然后获取每个存储库的问题,但返回 Observable<Issue>
不是修改后的 Observable<Repository>
,这就是我的情况。就我而言,我想用另一个返回不同可观察结果 (Observable<Data>
) 的请求的结果来修改以前的可观察结果 (Observable<[Book]>
)。
现在我有第一部分,下载书籍:
func search(query: String) -> Observable<[Book]>
return networkSession.rx
.data(request: URLRequest(url: url))
.map( try JSONDecoder().decode([Book].self, from: $0) )
Book
是一个简单的结构体:
struct Book
let title: String
let authors: [String]
let coverImageURL: URL
var coverImage: Data?
之后,我可以下载每个图像,但我不知道如何将其分配给每个对象,以便返回相同的 Observable<[Book]>
类型,而不会弄乱嵌套的 observables 和无数的编译时错误。我很确定这是使用flatMap
的常见场景,但它对我来说仍然有点模糊。
非常感谢!
【问题讨论】:
【参考方案1】:也许应该将 Book 结构拆分为两个结构。第一个在此处称为 BookInfo,并通过调用函数 search 下载它们的数组。
struct BookInfo
let title: String
let authors: [String]
let coverImageURL: URL
将 BookInfo 实例与 coverImage 数据组合在一起可能会导致 Book 结构如下:
struct Book
let bookInfo: BookInfo
let coverImage: Data
RxSwift 链如下所示:
self.search(query: "<someQuery>")
.flatMap (bookInfos: [BookInfo]) -> Observable<BookInfo> in
Observable.from(bookInfos)
.flatMap (bookInfo: BookInfo) -> Observable<Book> in
//use the coverImageURL from the closure parameter and fetch the coverImage
//return an Observable<Book>
.observeOn(MainScheduler.instance)
.do(onNext: (book: Book) in
//e.g. add a book in main thread to the UI once the cover image is available
)
.subscribe()
.disposed(by: disposeBag)
我没有使用类型推断,而是添加了显式类型规范,因此更明显的是什么样的元素通过链传递。
更新
如果你只想使用一个 Book 结构,你可以使用这个:
self.search(query: "<someQuery>")
.flatMap (books: [Book]) -> Observable<Book> in
Observable.from(books)
.flatMap (book: Book) -> Observable<Book> in
//use the book.coverImageURL from the closure parameter and fetch the coverImage
//since the closure parameter 'book' is a let constant you have to construct a new Book instance
//return an Observable<Book>
...
请注意,闭包参数是 let 常量。这意味着您不能更改 coverImage 属性,即使它在结构中定义为 var。相反,您必须创建 Book 结构的新实例,用来自 Closure 参数的值填充它,然后添加 coverImage 数据。因此,如果您想走这条路,您还可以选择将 coverImage 更改为 let 常量。
我想我个人会稍微偏爱使用这两个结构的第一种方法。
【讨论】:
很棒的方法,我喜欢它:D 我会试一试的。在接受您的回答之前,让我等待有人回答而不使用两个结构。 很高兴你喜欢它:D。我更新了答案并在不使用两个结构的情况下添加了第二种方法。 感谢您的更新,这正是我想要的 :)以上是关于RxSwift,依赖链的下载返回相同的 Observable 类型的主要内容,如果未能解决你的问题,请参考以下文章