合并 2 个 PublishSubject 并使用 Observable.combineLatest 发出
Combine 2 PublishSubject's and emit with Observable.combineLatest
我的服务中有 2 个独立的数据集合。
Featured
和 Standard
内容。
我对 return 这些项目打了 2 api 次电话。它们可以单独使用,但是我也有这样的用例,我想获取两组数据,根据条件提供一些丰富内容,然后 return 将它们提供给消费者。
我希望我能做这样的事情:
class ContentService: ContentServiceType {
let featured = PublishSubject<[Content]>()
let standard = PublishSubject<[Content]>()
let content: Observable<(featured: [Content], standard: [Content])>
private let client: Client<ContentAPI>
private let disposeBag = DisposeBag()
init(client: Client<ContentAPI>) {
self.client = client
content = Observable
.combineLatest(featured, standard)
.map { (featured, standard) -> (featured: [Content], standard: [Content]) in
/*
Do some enrichment and create then return new, updated versions
*/
return (featured: updatedFeatured, standard: updatedStandard)
}.share()
}
func fetchStandardContent(page: Int = 0, size: Int = 100) -> Single<Void> {
let params = ["page": page, "size": size]
let request: Single<Content> = client.request(.getStandardContent(params))
return request.map { [unowned self] launchers in
self.standard.onNext(content.props)
return ()
}
}
func fetchFeaturedContent(page: Int = 0, size: Int = 100) -> Single<Void> {
let params = ["page": page, "size": size]
let request: Single<Content> = client.request(.getFeaturedContent(params))
return request.map { [unowned self] content in
self.featured.onNext(content.props)
return ()
}
}
}
在我的应用程序的其他地方,我当时希望我可以做类似
的事情
contentSvc.content
.observeOn(MainScheduler.instance)
.subscribeOn(ConcurrentDispatchQueueScheduler(qos: .background))
.subscribe(onNext: { content in
/* do something w/ content */
}).disposed(by: disposeBag)
然后每当调用 contentSvc.fetchFeaturedContent
或 contentSvc.fetchStandardContent
时,上面的 contentSvc.content
订阅者就会获取新数据。
相反 content
似乎没有发出任何值。
我相信 combineLatest
需要两个源都发出才能发出自己。
我可能会考虑使用 BehaviorSubject
或 BehaviorRelay
而不是 PublishSubject。
我使用 BehaviorRelay 而不是 PublishSubject,因为当从多个流绑定到 PublishSubject(跨应用程序共享)时,如果这些流中的任何一个发送完整的,PublishSubject 可能会终止。中继 类 从不产生错误或从不完成。
let featured = BehaviorRelay(value: [Content]())
let standard = BehaviorRelay(value: [Content]())
func getContent() -> Observable<(featured: [Content], standard: [Content])> {
return Observable
.combineLatest(
featured.asObservable(),
standard.asObservable(),
resultSelector: { (featured, standard) -> (featured: [Content], standard: [Content]) in
return (featured: featured, standard: standard)
}
)
}
func addElemToFeatured() {
featured.accept([Content(name: "abc")])
}
func addElemToStandard() {
standard.accept([Content(name: "xyz")])
}
在初始化方法中从不同的 类 调用 getContent() 方法。还可以从按钮操作等不同位置调用 addElemToFeatured、addElemToStandard。
listener!.getContent()
.subscribe(onNext: { (featured, standard) in
print(featured)
print(standard)
}).disposed(by: disposeBag)
我的服务中有 2 个独立的数据集合。
Featured
和 Standard
内容。
我对 return 这些项目打了 2 api 次电话。它们可以单独使用,但是我也有这样的用例,我想获取两组数据,根据条件提供一些丰富内容,然后 return 将它们提供给消费者。
我希望我能做这样的事情:
class ContentService: ContentServiceType {
let featured = PublishSubject<[Content]>()
let standard = PublishSubject<[Content]>()
let content: Observable<(featured: [Content], standard: [Content])>
private let client: Client<ContentAPI>
private let disposeBag = DisposeBag()
init(client: Client<ContentAPI>) {
self.client = client
content = Observable
.combineLatest(featured, standard)
.map { (featured, standard) -> (featured: [Content], standard: [Content]) in
/*
Do some enrichment and create then return new, updated versions
*/
return (featured: updatedFeatured, standard: updatedStandard)
}.share()
}
func fetchStandardContent(page: Int = 0, size: Int = 100) -> Single<Void> {
let params = ["page": page, "size": size]
let request: Single<Content> = client.request(.getStandardContent(params))
return request.map { [unowned self] launchers in
self.standard.onNext(content.props)
return ()
}
}
func fetchFeaturedContent(page: Int = 0, size: Int = 100) -> Single<Void> {
let params = ["page": page, "size": size]
let request: Single<Content> = client.request(.getFeaturedContent(params))
return request.map { [unowned self] content in
self.featured.onNext(content.props)
return ()
}
}
}
在我的应用程序的其他地方,我当时希望我可以做类似
的事情 contentSvc.content
.observeOn(MainScheduler.instance)
.subscribeOn(ConcurrentDispatchQueueScheduler(qos: .background))
.subscribe(onNext: { content in
/* do something w/ content */
}).disposed(by: disposeBag)
然后每当调用 contentSvc.fetchFeaturedContent
或 contentSvc.fetchStandardContent
时,上面的 contentSvc.content
订阅者就会获取新数据。
相反 content
似乎没有发出任何值。
combineLatest
需要两个源都发出才能发出自己。
我可能会考虑使用 BehaviorSubject
或 BehaviorRelay
而不是 PublishSubject。
我使用 BehaviorRelay 而不是 PublishSubject,因为当从多个流绑定到 PublishSubject(跨应用程序共享)时,如果这些流中的任何一个发送完整的,PublishSubject 可能会终止。中继 类 从不产生错误或从不完成。
let featured = BehaviorRelay(value: [Content]())
let standard = BehaviorRelay(value: [Content]())
func getContent() -> Observable<(featured: [Content], standard: [Content])> {
return Observable
.combineLatest(
featured.asObservable(),
standard.asObservable(),
resultSelector: { (featured, standard) -> (featured: [Content], standard: [Content]) in
return (featured: featured, standard: standard)
}
)
}
func addElemToFeatured() {
featured.accept([Content(name: "abc")])
}
func addElemToStandard() {
standard.accept([Content(name: "xyz")])
}
在初始化方法中从不同的 类 调用 getContent() 方法。还可以从按钮操作等不同位置调用 addElemToFeatured、addElemToStandard。
listener!.getContent()
.subscribe(onNext: { (featured, standard) in
print(featured)
print(standard)
}).disposed(by: disposeBag)