我試圖了解如何使用 Combine 鏈接然后重新組合一對多網路查詢。
我有一個初始請求,它檢索一些 JSON 資料,對其進行解碼并將其映射到一個 ID 串列:
let _ = URLSession.shared
.dataTaskPublisher(for: url)
.receive(on: apiQueue)
.map(\.data)
.decode(type: MyMainResultType.self, decoder: JSONDecoder())
.map { $0.results.map { $0.id } } // 'results' is a struct containing 'id', among others
// .sink() and .store() omitted
這給了我預期的整數陣列:[123, 456, ...]
對于每個整數,我想啟動另一個請求,該請求使用該 ID 作為引數查詢另一個端點,檢索一些 JSON,提取一段適當的資料,然后將其與 ID 重新組合以給我一個最終的[(id, otherData), ...].
第二個請求作為一個獨立的函式作業,有自己的sink()and store(),也作為AnyPublisher<>.
我嘗試了任意數量的map { Publishers.Sequence ...},等.flatMap(),.combine()但我認為我對正在發生的事情的心理模型可能是不正確的。
我認為我應該做的是map()對次要詳細資訊請求發布者的每個 int,然后執行 aflatMap()以取回單個發布者,并獲取collect()所有結果,可能使用另一張地圖來引入 ID,但似乎沒有什么能給我簡單的串列,如上所述,最后。
如何獲取我的整數串列并產生一些進一步的請求,等到所有請求都完成,然后將 id 和附加資訊重新組合到單個組合鏈中?
蒂亞!
uj5u.com熱心網友回復:
在現有管道之后,您應該flatMap首先Publishers.Sequence:
.flatMap(\.publisher)
此更改將您的發布者從發布事物陣列的發布者轉變為發布這些陣列元素的發布者。
然后對 URL 會話資料任務發布者進行另一個平面映射,并附上所有提取步驟otherData。請注意,最后是我們關聯id的地方otherData:
.flatMap { id in
URLSession.shared.dataTaskPublisher(
// as an example
for: URL(string: "https://example.com/?id=\(id)")!
).receive(on: apiQueue)
.map(\.data)
.decode(type: Foo.self, decoder: JSONDecoder())
.map { (id, $0.otherData) } // associate id with otherData
}
然后你可以collect()把它變成一個只發布陣列的發布者。
完整版本:
// this is of type AnyPublisher<[(Int, Int)], Error>
let _ = URLSession.shared
.dataTaskPublisher(for: url)
.receive(on: apiQueue)
.map(\.data)
.decode(type: MyMainResultType.self, decoder: JSONDecoder())
.map { $0.results.map { $0.id } }
.flatMap(\.publisher)
.flatMap { id in
URLSession.shared.dataTaskPublisher(
// as an example
for: URL(string: "https://example.com/?id=\(id)")!
).receive(on: apiQueue)
.map(\.data)
.decode(type: Foo.self, decoder: JSONDecoder())
.map { (id, $0.otherData) } // associate id with otherData
}
.collect()
.eraseToAnyPublisher()
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/491671.html
