RxSwift:将两个网络请求合并为 return 个值
RxSwift: Combine two network request to return one value
我有两个网络请求,我想将结果合并到一个对象数组中。
enum ResultType<T> {
case success(T)
case failure(Error)
}
static func requestPlaceSearch(query: String) -> Observable<ResultType<SearchResult>> {
let urlString = "https://maps.googleapis.com/maps/api/place/autocomplete/json"
let params = ["input": query, "types": "geocode",
"key": "key"]
return placeRequest(url: urlString, params: params)
}
static func requestPlace(with placeId: String) -> Observable<ResultType<Place>> {
let params = ["placeid": placeId, "key": "key"]
let urlString = "https://maps.googleapis.com/maps/api/place/details/json"
return placeRequest(url: urlString, params: params)
}
requestPlaceSearch
returns 和 SearchResult
的可观察性
我想遍历 SearchResult.predictions
,获取每个预测的 ID 请求 requestPlace
获取 Place
并附加到 Places
的数组
我希望我的最终数组是
let places = Observable<[Place]>
或
let places = [Place]()
我会给你答案,但我会通过解释我是如何得出答案的来把它画出来的。希望您可以模拟这个过程,并在下一次尝试中自己得出答案。
开始于:
let foo = requestPlaceSearch(query: "")
然后查看 foo
的类型,即:Observable<ResultType<SearchResult>>
。好的,我们需要从结果类型中提取搜索结果。所以...
let foo = requestPlaceSearch(query: "")
.map { (result: ResultType<SearchResult>) -> SearchResult? in
if case let .success(search) = result {
return search
} else {
return nil
}
}
现在foo
的类型是什么? Observable<SearchResult?>
。所以让我们过滤掉选项。
let foo = requestPlaceSearch(query: "")
.map { (result: ResultType<SearchResult>) -> SearchResult? in
if case let .success(search) = result {
return search
} else {
return nil
}
}
.filter { [=12=] != nil }.map { [=12=]! }
现在 foo
的类型是:Observable<SearchResult>
所以我们可以提取 predictions
.
let foo = requestPlaceSearch(query: "")
.map { (result: ResultType<SearchResult>) -> SearchResult? in
if case let .success(search) = result {
return search
} else {
return nil
}
}
.filter { [=13=] != nil }.map { [=13=]! }
.map { [=13=].predictions }
我们将需要该函数再次提取成功对象,所以让我们将其移至一个单独的函数中:
func extractSuccess<T>(_ result: ResultType<T>) -> T? {
if case let .success(search) = result {
return search
} else {
return nil
}
}
我假设 predictions
只是字符串。您可能必须从中提取字符串 ID。所以现在 foo 的类型是 Observable<[String]>
。现在我们有了 ID,我们可以调用另一个端点。
let foo = requestPlaceSearch(query: "")
.map(extractSuccess)
.filter { [=15=] != nil }.map { [=15=]! }
.map { [=15=].predictions }
.map { [=15=].map(requestPlace) }
现在 foo
是 Observable<[Observable<ResultType<Place>>]>
类型。接下来让我们把 [Observable] 变成 Observable<[T]>.
let foo = requestPlaceSearch(query: "")
.map(extractSuccess)
.filter { [=16=] != nil }.map { [=16=]! }
.map { [=16=].predictions }
.map { Observable.combineLatest([=16=].map(requestPlace)) }
这使得 foo 成为 Observable<Observable<[ResultType<Place>]>>
。 Observable> 可以很容易地展平。
let foo = requestPlaceSearch(query: "")
.map(extractSuccess)
.filter { [=17=] != nil }.map { [=17=]! }
.map { [=17=].predictions }
.flatMap { Observable.combineLatest([=17=].map(requestPlace)) }
将 foo 变成 Observable<[ResultType<Place>]>
let foo = requestPlaceSearch(query: "")
.map(extractSuccess)
.filter { [=18=] != nil }.map { [=18=]! }
.map { [=18=].predictions }
.flatMap { Observable.combineLatest([=18=].map {
requestPlace(with: [=18=])
.map(extractSuccess)
.filter { [=18=] != nil }.map { [=18=]! }
})
}
我在上面添加的部分与上一个returns结果类型相同。另外,此时 foo
是 Observable<[Place]>
类型,我们就完成了。
请注意,此代码不处理任何失败结果。我将把它留作 reader 的练习。 :-)
我有两个网络请求,我想将结果合并到一个对象数组中。
enum ResultType<T> {
case success(T)
case failure(Error)
}
static func requestPlaceSearch(query: String) -> Observable<ResultType<SearchResult>> {
let urlString = "https://maps.googleapis.com/maps/api/place/autocomplete/json"
let params = ["input": query, "types": "geocode",
"key": "key"]
return placeRequest(url: urlString, params: params)
}
static func requestPlace(with placeId: String) -> Observable<ResultType<Place>> {
let params = ["placeid": placeId, "key": "key"]
let urlString = "https://maps.googleapis.com/maps/api/place/details/json"
return placeRequest(url: urlString, params: params)
}
requestPlaceSearch
returns 和 SearchResult
的可观察性
我想遍历 SearchResult.predictions
,获取每个预测的 ID 请求 requestPlace
获取 Place
并附加到 Places
我希望我的最终数组是
let places = Observable<[Place]>
或
let places = [Place]()
我会给你答案,但我会通过解释我是如何得出答案的来把它画出来的。希望您可以模拟这个过程,并在下一次尝试中自己得出答案。
开始于:
let foo = requestPlaceSearch(query: "")
然后查看 foo
的类型,即:Observable<ResultType<SearchResult>>
。好的,我们需要从结果类型中提取搜索结果。所以...
let foo = requestPlaceSearch(query: "")
.map { (result: ResultType<SearchResult>) -> SearchResult? in
if case let .success(search) = result {
return search
} else {
return nil
}
}
现在foo
的类型是什么? Observable<SearchResult?>
。所以让我们过滤掉选项。
let foo = requestPlaceSearch(query: "")
.map { (result: ResultType<SearchResult>) -> SearchResult? in
if case let .success(search) = result {
return search
} else {
return nil
}
}
.filter { [=12=] != nil }.map { [=12=]! }
现在 foo
的类型是:Observable<SearchResult>
所以我们可以提取 predictions
.
let foo = requestPlaceSearch(query: "")
.map { (result: ResultType<SearchResult>) -> SearchResult? in
if case let .success(search) = result {
return search
} else {
return nil
}
}
.filter { [=13=] != nil }.map { [=13=]! }
.map { [=13=].predictions }
我们将需要该函数再次提取成功对象,所以让我们将其移至一个单独的函数中:
func extractSuccess<T>(_ result: ResultType<T>) -> T? {
if case let .success(search) = result {
return search
} else {
return nil
}
}
我假设 predictions
只是字符串。您可能必须从中提取字符串 ID。所以现在 foo 的类型是 Observable<[String]>
。现在我们有了 ID,我们可以调用另一个端点。
let foo = requestPlaceSearch(query: "")
.map(extractSuccess)
.filter { [=15=] != nil }.map { [=15=]! }
.map { [=15=].predictions }
.map { [=15=].map(requestPlace) }
现在 foo
是 Observable<[Observable<ResultType<Place>>]>
类型。接下来让我们把 [Observable] 变成 Observable<[T]>.
let foo = requestPlaceSearch(query: "")
.map(extractSuccess)
.filter { [=16=] != nil }.map { [=16=]! }
.map { [=16=].predictions }
.map { Observable.combineLatest([=16=].map(requestPlace)) }
这使得 foo 成为 Observable<Observable<[ResultType<Place>]>>
。 Observable> 可以很容易地展平。
let foo = requestPlaceSearch(query: "")
.map(extractSuccess)
.filter { [=17=] != nil }.map { [=17=]! }
.map { [=17=].predictions }
.flatMap { Observable.combineLatest([=17=].map(requestPlace)) }
将 foo 变成 Observable<[ResultType<Place>]>
let foo = requestPlaceSearch(query: "")
.map(extractSuccess)
.filter { [=18=] != nil }.map { [=18=]! }
.map { [=18=].predictions }
.flatMap { Observable.combineLatest([=18=].map {
requestPlace(with: [=18=])
.map(extractSuccess)
.filter { [=18=] != nil }.map { [=18=]! }
})
}
我在上面添加的部分与上一个returns结果类型相同。另外,此时 foo
是 Observable<[Place]>
类型,我们就完成了。
请注意,此代码不处理任何失败结果。我将把它留作 reader 的练习。 :-)