swift - 使用 RxSwift 链接请求并返回两个结果
问题描述
我有ContentService
一个请求一篇文章的请求。该文章响应包含一个authorId
属性。
我有一个ProfileService
允许我通过userId
.
我正在尝试从ContentService
, 链上请求一篇文章,一旦完成ProfileService
使用该authorId
属性,我想返回一个ContentArticleViewModel
包含文章和个人资料信息的文章。
我的ArticleInteractor
长相是这样的——
final class ArticleInteractor: ArticleInteractorInputProtocol {
let fetchArticleTrigger = PublishSubject<String>()
private lazy var disposeBag = DisposeBag()
weak var output: ArticleInteractorOutputProtocol? {
didSet {
configureSubscriptions()
}
}
private func configureSubscriptions() {
guard let output = output else { return }
fetchArticleTrigger
.bind(to: dependencies.contentSvc.fetchContentByIdTrigger)
.disposed(by: disposeBag)
dependencies.contentSvc.fetchContentByIdResponse
.bind(to: output.fetchArticleResponse)
.disposed(by: disposeBag)
}
}
很简单地fetchArticleTrigger
开始一个请求,然后我继续bind
并dependencies.contentSvc.fetchContentByIdResponse
拿起响应。
我的方法ContentService
是 -
// MARK:- FetchContentById
// @params: id - String
// return: PublishSubject<ContentArticle>
fetchContentByIdTrigger
.flatMapLatest { [unowned self] in self.client.request(.getContentById(id: $0)) }
.map { (resp: Result<ContentArticle>) in
guard case .success(let props) = resp else { return ContentArticle() }
return props
}
.bind(to: fetchContentByIdResponse)
.disposed(by: disposeBag)
我有一个非常相似的设置ProfileService
-
// MARK:- FetchUserProfileById
// @params: id - String
// return: PublishSubject<User>
fetchUserProfileByIdTrigger
.flatMapLatest { [unowned self] in self.client.request(.getProfileByUserId(id: $0)) }
.map { (resp: Result<User>) in
guard case .success(let props) = resp else { return User() }
return props
}
.bind(to: fetchUserProfileByIdResponse)
.disposed(by: disposeBag)
我想我会为这篇文章创建一个模型,比如——
struct ContentArticleViewModel {
var post: ContentArticle
var user: User
}
我在我的ArticleInteractor
-
dependencies.contentSvc.fetchContentByIdResponse
.flatMapLatest { article in
/* fetch profile using `article.authorId */
}.map { article, profile in
return ContentArticleViewModel(post: article, user: profile)
}
.bind(to: output.fetchArticleResponse)
.disposed(by: disposeBag)
但我完全不知道如何最好地处理这个问题。我看过很多关于链接请求的文章,但我很难成功地应用任何东西。
编辑
我目前有一些工作 -
private func configureSubscriptions() {
guard let output = output else { return }
fetchArticleTrigger
.bind(to: dependencies.contentSvc.fetchContentByIdTrigger)
.disposed(by: disposeBag)
dependencies.contentSvc.fetchContentByIdResponse
.do(onNext: { [unowned self] article in self.dependencies.profileSvc.fetchUserProfileByIdTrigger.onNext(article.creator.userId)})
.bind(to: fetchArticleResponse)
.disposed(by: disposeBag)
let resp = Observable.combineLatest(fetchArticleResponse, dependencies.profileSvc.fetchUserProfileByIdResponse)
resp
.map { [unowned self] in self.enrichArticleAuthorProps(article: $0, user: $1) }
.bind(to: output.fetchArticleResponse)
.disposed(by: disposeBag)
}
private func enrichArticleAuthorProps(article: ContentArticle, user: User) -> ContentArticle {
var updatedArticle = article
updatedArticle.creator = user
return updatedArticle
}
但是,我不确定这是否正确。
解决方案
我不确定为什么你有这么多代码来完成这么小的工作。下面是一个示例,它执行您所描述的操作(下载文章,下载作者个人资料并发出两者),代码少得多,甚至比我通常使用的代码多。
protocol ContentService {
func requestArticle(id: String) -> Observable<Article>
func requestProfile(id: String) -> Observable<User>
}
class Example {
let service: ContentService
init(service: ContentService) {
self.service = service
}
func bind(trigger: Observable<String>) -> Observable<(Article, User)> {
let service = self.service
return trigger
.flatMapLatest { service.requestArticle(id: $0) }
.flatMapLatest {
Observable.combineLatest(Observable.just($0), service.requestProfile(id: $0.authorId))
}
}
}
或者,您可能希望在等待作者简介下载时显示文章。在这种情况下是这样的:
func bind(trigger: Observable<String>) -> (article: Observable<Article>, author: Observable<User>) {
let service = self.service
let article = trigger
.flatMapLatest { service.requestArticle(id: $0) }
.share(replay: 1)
let author = article
.flatMapLatest {
service.requestProfile(id: $0.authorId)
}
return (article, author)
}
推荐阅读
- c++ - 正方体总是缺少图片中的文本行
- python - AttributeError:模块“tensorflow”没有属性“compat”
- python - 将 JSON 解析为不带前缀的 Pandas
- ruby-on-rails - 葡萄添加新端点
- mongodb - Spring Boot Mongo DB中无法解析的日期错误格式
- sas - 用于内核密度 SAS 的默认值
- node.js - UnhandledPromiseRejectionWarning: 错误: 禁止 SendGrid WebAPI 错误
- docker - 如何在 ecs2 fargate 中通过 docker-compose up 运行 docker
- java - 在 Android 中运行 SQLite 查询
- c++ - 如何移动 QListWidgetItem?