RxSwift 中的链式请求使用第一个请求来设置更多请求,然后 return 全部完成
Chain requests in RxSwift using first request to setup further requests then return all when complete
我有一个要求 Article
。
每个 Article
包含一个 ArticleAsset
的数组,其中包含渲染整篇文章时我需要的各种道具。
我事先不知道一篇文章有多少资产,所以我必须请求这篇文章,然后使用 assets
prop dispatch X amount of request 到 return 的值每个 ArticleAsset
.
到那时我应该 return 我的资产提取的文章和结果数组。
为简单起见,假设在这种情况下每个资产 return 都是 Int
。所以我从这个开始 -
Article
> [Article]
我希望最终得到如下形状的元组 (article: Article, assets: [Int])
我试图将其重新创建为下面的游乐场,但完全没有成功,有点卡住了。
我了解如何使用 flatMapLatest
等链接固定数量的请求,但在这种情况下我不知道请求的数量。我在想我应该为每个 ArticleAsset
和 return 映射一个 Observables
的数组,但是我开始对下一步要去哪里感到非常模糊。
如有任何帮助,我们将不胜感激,谢谢。
import UIKit
import RxSwift
private let disposeBag = DisposeBag()
struct Article {
let id: UUID = UUID()
var assets: [ArticleAsset]
}
struct ArticleAsset {
let number: Int
}
let assets: [ArticleAsset] = Array(0...4).map { ArticleAsset(number: [=11=]) }
let article = Article(assets: assets)
func fetchArticle() -> Observable<Article> {
return Observable.of(article)
}
func getArticleAsset(asset: ArticleAsset) -> Observable<Int> {
return .of(asset.number)
}
fetchArticle()
.map { art in
let assets = art.assets.map { getArticleAsset(asset: [=11=]) }
let resp = (article: art, assets: Observable.of(assets))
return resp
}.subscribe(onNext: { resp in
// I would like my subscriber to receive (article: Article, assets: [Int])
}).disposed(by: disposeBag)
Rx 有几个扁平化运算符。 flatMapLatest
不是你想要的,因为它只会给你最后一个内部观察的结果。您真正想要的是合并所有 ArticleAsset 流,并仅在它们全部完成后才继续。因此,您想 merge
所有 ArticleAsset 请求,然后 reduce
将它们放入 ArticleAsset 数组中。
fetchArticle()
.flatMap { article in
let allAssetRequests = article.assets.map {
getArticleAsset(asset: article)
}
return Observable
.merge(allAssetRequests)
.reduce([ArticleAsset]()) { array, asset in
//Combine here
}
}
您可以在此处更改 reduce
以缩减为一个元组:(Article, [ArticleAsset])
然后您将获得您要查找的流的最终形式。
制作可编译游乐场的荣誉!这让事情变得容易多了。你想在这里做的是结合可观察量。 In my article 你会发现有很多方法可以做到这一点。我认为对于这个用例,zip
运算符是最好的。
let articleWithAssets = fetchArticle()
.flatMap { (article) -> Observable<(article: Article, assets: [Int])> in
let articles = Observable.zip(article.assets.map { getArticleAsset(asset: [=10=]) })
return Observable.zip(Observable.just(article), articles) { (article: [=10=], assets: ) }
}
articleWithAssets
.subscribe(onNext: { resp in
// here `resp` is of type `(article: Article, assets: [Int])` as requested.
})
当fetchArticle()
发出一个值时,flatMap
s闭包将被调用,它会为每个资产调用getArticleAsset(asset:)
,等到它们全部完成,将它们组合成一个单个 Observable 数组(articles
对象),然后将其与 .just(article)
observable 组合。
警告,如果任何 one 资产请求失败,则整个链都会失败。如果你不想要那个,你将不得不在 { getArticleAsset(asset: [=17=]) }
块中处理它。 (也许会发出 nil 或 missingAsset
资产。)
我有一个要求 Article
。
每个 Article
包含一个 ArticleAsset
的数组,其中包含渲染整篇文章时我需要的各种道具。
我事先不知道一篇文章有多少资产,所以我必须请求这篇文章,然后使用 assets
prop dispatch X amount of request 到 return 的值每个 ArticleAsset
.
到那时我应该 return 我的资产提取的文章和结果数组。
为简单起见,假设在这种情况下每个资产 return 都是 Int
。所以我从这个开始 -
Article
> [Article]
我希望最终得到如下形状的元组 (article: Article, assets: [Int])
我试图将其重新创建为下面的游乐场,但完全没有成功,有点卡住了。
我了解如何使用 flatMapLatest
等链接固定数量的请求,但在这种情况下我不知道请求的数量。我在想我应该为每个 ArticleAsset
和 return 映射一个 Observables
的数组,但是我开始对下一步要去哪里感到非常模糊。
如有任何帮助,我们将不胜感激,谢谢。
import UIKit
import RxSwift
private let disposeBag = DisposeBag()
struct Article {
let id: UUID = UUID()
var assets: [ArticleAsset]
}
struct ArticleAsset {
let number: Int
}
let assets: [ArticleAsset] = Array(0...4).map { ArticleAsset(number: [=11=]) }
let article = Article(assets: assets)
func fetchArticle() -> Observable<Article> {
return Observable.of(article)
}
func getArticleAsset(asset: ArticleAsset) -> Observable<Int> {
return .of(asset.number)
}
fetchArticle()
.map { art in
let assets = art.assets.map { getArticleAsset(asset: [=11=]) }
let resp = (article: art, assets: Observable.of(assets))
return resp
}.subscribe(onNext: { resp in
// I would like my subscriber to receive (article: Article, assets: [Int])
}).disposed(by: disposeBag)
Rx 有几个扁平化运算符。 flatMapLatest
不是你想要的,因为它只会给你最后一个内部观察的结果。您真正想要的是合并所有 ArticleAsset 流,并仅在它们全部完成后才继续。因此,您想 merge
所有 ArticleAsset 请求,然后 reduce
将它们放入 ArticleAsset 数组中。
fetchArticle()
.flatMap { article in
let allAssetRequests = article.assets.map {
getArticleAsset(asset: article)
}
return Observable
.merge(allAssetRequests)
.reduce([ArticleAsset]()) { array, asset in
//Combine here
}
}
您可以在此处更改 reduce
以缩减为一个元组:(Article, [ArticleAsset])
然后您将获得您要查找的流的最终形式。
制作可编译游乐场的荣誉!这让事情变得容易多了。你想在这里做的是结合可观察量。 In my article 你会发现有很多方法可以做到这一点。我认为对于这个用例,zip
运算符是最好的。
let articleWithAssets = fetchArticle()
.flatMap { (article) -> Observable<(article: Article, assets: [Int])> in
let articles = Observable.zip(article.assets.map { getArticleAsset(asset: [=10=]) })
return Observable.zip(Observable.just(article), articles) { (article: [=10=], assets: ) }
}
articleWithAssets
.subscribe(onNext: { resp in
// here `resp` is of type `(article: Article, assets: [Int])` as requested.
})
当fetchArticle()
发出一个值时,flatMap
s闭包将被调用,它会为每个资产调用getArticleAsset(asset:)
,等到它们全部完成,将它们组合成一个单个 Observable 数组(articles
对象),然后将其与 .just(article)
observable 组合。
警告,如果任何 one 资产请求失败,则整个链都会失败。如果你不想要那个,你将不得不在 { getArticleAsset(asset: [=17=]) }
块中处理它。 (也许会发出 nil 或 missingAsset
资产。)