我有两个网络请求,希望将结果合并到一个对象数组中。
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
返回并观察到SearchResult
我想遍历SearchResult.predictions
,获取每个预测的ID,向requestPlace
发出请求,获取Place
到Places
数组的追加
我希望我的最终数组为
let places = Observable<[Place]>
或
let places = [Place]()
答案 0 :(得分:2)
我将为您提供答案,但我将通过解释我是如何得出答案来将其画出来的。希望您可以模拟该过程,并能够在下次尝试中自己提出答案。
开始于:
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 { $0 != nil }.map { $0! }
现在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 { $0 != nil }.map { $0! }
.map { $0.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 { $0 != nil }.map { $0! }
.map { $0.predictions }
.map { $0.map(requestPlace) }
现在foo
的类型为Observable<[Observable<ResultType<Place>>]>
。接下来,让我们将[Observable]变为Observable <[T]>。
let foo = requestPlaceSearch(query: "")
.map(extractSuccess)
.filter { $0 != nil }.map { $0! }
.map { $0.predictions }
.map { Observable.combineLatest($0.map(requestPlace)) }
将foo设为Observable<Observable<[ResultType<Place>]>>
。可以很容易地将Observable>展平。
let foo = requestPlaceSearch(query: "")
.map(extractSuccess)
.filter { $0 != nil }.map { $0! }
.map { $0.predictions }
.flatMap { Observable.combineLatest($0.map(requestPlace)) }
这会使foo变成Observable<[ResultType<Place>]>
let foo = requestPlaceSearch(query: "")
.map(extractSuccess)
.filter { $0 != nil }.map { $0! }
.map { $0.predictions }
.flatMap { Observable.combineLatest($0.map {
requestPlace(with: $0)
.map(extractSuccess)
.filter { $0 != nil }.map { $0! }
})
}
我在上面添加的部分与最后一个返回结果类型的部分相同。而且,此时foo
的类型为Observable<[Place]>
,我们就完成了。
请注意,此代码不处理任何失败结果。我将其留给读者练习。 :-)