如何使用 Combine Framework 进行多个请求
How to have multiple requests using Combine Framework
我目前正在为我的 SwiftUI 项目使用 Moya alpha 15 和 Combine Framework。使用 Moya,我有一个负责创建请求的提供程序。
我想要的:
- 使用 getInstance(page: Int) 获取我的初始 instanceResponseList object。
- 从那个 instanceResponseList object,检查每个实例是否 hasChildren == true
- 如果 hasChildren == true,使用实例的 id 调用 getInstanceChildren(id: String)
- 来自 getInstanceChildren(id: String) 的响应将被映射并分配给 children: [Instance] 属性(response.data.instances)
这可能吗?如果没有,有更好的方法吗?
我想做什么:
我需要在 tableView 中使用 Instance 的 profileURL 显示个人资料图像。每个单元格的高度将是动态的,并基于每个图像的纵横比。每个单元格可以有 1 + children 个不同排列的个人资料图像。
我的服务调用和数据模型的一些示例代码:
public struct InstanceResponseList: Codable {
public var success: Bool
public var data: InstanceResponse
}
public struct InstanceResponse: Codable {
public var instances: [Instance]
public var hasMore: Bool //for pagination
}
public struct Instance: Codable {
public var id: String
public var profileURL: String?
public var hasChildren: Bool
public var children: [Instance] // I want to make a request and append the children for each of my instances.
enum CodingKeys: String, CodingKey {
case id = "instance_id"
case profileURL = "profile_url"
case hasChildren = "has_children"
}
}
public func getInstance(page: Int) -> AnyPublisher<InstanceResponseList, MoyaError> {
return instanceProvider
.requestPublisher(.allInstances(page: page, show: 10)) // page & show are parameters used for pagination, not relevant here
.map(InstanceResponseList.self)
.receive(on: DispatchQueue.main)
.eraseToAnyPublisher()
}
public func getInstanceChildren(id: String) -> AnyPublisher<InstanceResponseList, MoyaError> {
return haptagramProvider
.requestPublisher(.children(id: id))
.map(InstanceResponseList.self)
.receive(on: DispatchQueue.main)
.eraseToAnyPublisher()
}
我的尝试:
public func getInstanceWithChildren(page: Int) -> AnyPublisher<[Instance], MoyaError> {
return getInstance(page: Int)
.flatMap { instanceResponseList -> AnyPublisher<Instance, MoyaError> in
Publishers.Sequence(sequence: instanceResponseList.data.instances).eraseToAnyPublisher()
}
.flatMap { instance -> AnyPublisher<Instance, MoyaError> in
return getInstanceChildren(id: instance.id).map {
let instance = instance
instance.children = [=11=]
return instance
}
.eraseToAnyPublisher()
}
.collect()
.eraseToAnyPublisher()
}
which returns AnyPublisher<[Instance], MoyaError>
, 但我正在寻找 return AnyPublisher<InstanceResponseList, MoyaError>
.
你所做的大部分是正确的。您只需要另一层嵌套即可获得原始 instanceResponseList
值:
getInstance(page: page)
.flatMap { instanceResponseList in
Publishers.Sequence(sequence: instanceResponseList.data.instances)
.flatMap { instance in
instance.hasChildren
? getInstanceChildren(id: instance.id)
.map { children -> Instance in
var instance = instance
instance.children = children
return instance
}
.eraseToAnyPublisher()
: Just(instance)
.setFailureType(to: MoyaError.self)
.eraseToAnyPublisher()
}
.collect()
.map { instances -> InstanceResponseList in
var instanceResponseList = instanceResponseList
instanceResponseList.data.instances = instances
return instanceResponseList
}
}
.eraseToAnyPublisher()
我目前正在为我的 SwiftUI 项目使用 Moya alpha 15 和 Combine Framework。使用 Moya,我有一个负责创建请求的提供程序。
我想要的:
- 使用 getInstance(page: Int) 获取我的初始 instanceResponseList object。
- 从那个 instanceResponseList object,检查每个实例是否 hasChildren == true
- 如果 hasChildren == true,使用实例的 id 调用 getInstanceChildren(id: String)
- 来自 getInstanceChildren(id: String) 的响应将被映射并分配给 children: [Instance] 属性(response.data.instances)
这可能吗?如果没有,有更好的方法吗?
我想做什么:
我需要在 tableView 中使用 Instance 的 profileURL 显示个人资料图像。每个单元格的高度将是动态的,并基于每个图像的纵横比。每个单元格可以有 1 + children 个不同排列的个人资料图像。
我的服务调用和数据模型的一些示例代码:
public struct InstanceResponseList: Codable {
public var success: Bool
public var data: InstanceResponse
}
public struct InstanceResponse: Codable {
public var instances: [Instance]
public var hasMore: Bool //for pagination
}
public struct Instance: Codable {
public var id: String
public var profileURL: String?
public var hasChildren: Bool
public var children: [Instance] // I want to make a request and append the children for each of my instances.
enum CodingKeys: String, CodingKey {
case id = "instance_id"
case profileURL = "profile_url"
case hasChildren = "has_children"
}
}
public func getInstance(page: Int) -> AnyPublisher<InstanceResponseList, MoyaError> {
return instanceProvider
.requestPublisher(.allInstances(page: page, show: 10)) // page & show are parameters used for pagination, not relevant here
.map(InstanceResponseList.self)
.receive(on: DispatchQueue.main)
.eraseToAnyPublisher()
}
public func getInstanceChildren(id: String) -> AnyPublisher<InstanceResponseList, MoyaError> {
return haptagramProvider
.requestPublisher(.children(id: id))
.map(InstanceResponseList.self)
.receive(on: DispatchQueue.main)
.eraseToAnyPublisher()
}
我的尝试:
public func getInstanceWithChildren(page: Int) -> AnyPublisher<[Instance], MoyaError> {
return getInstance(page: Int)
.flatMap { instanceResponseList -> AnyPublisher<Instance, MoyaError> in
Publishers.Sequence(sequence: instanceResponseList.data.instances).eraseToAnyPublisher()
}
.flatMap { instance -> AnyPublisher<Instance, MoyaError> in
return getInstanceChildren(id: instance.id).map {
let instance = instance
instance.children = [=11=]
return instance
}
.eraseToAnyPublisher()
}
.collect()
.eraseToAnyPublisher()
}
which returns AnyPublisher<[Instance], MoyaError>
, 但我正在寻找 return AnyPublisher<InstanceResponseList, MoyaError>
.
你所做的大部分是正确的。您只需要另一层嵌套即可获得原始 instanceResponseList
值:
getInstance(page: page)
.flatMap { instanceResponseList in
Publishers.Sequence(sequence: instanceResponseList.data.instances)
.flatMap { instance in
instance.hasChildren
? getInstanceChildren(id: instance.id)
.map { children -> Instance in
var instance = instance
instance.children = children
return instance
}
.eraseToAnyPublisher()
: Just(instance)
.setFailureType(to: MoyaError.self)
.eraseToAnyPublisher()
}
.collect()
.map { instances -> InstanceResponseList in
var instanceResponseList = instanceResponseList
instanceResponseList.data.instances = instances
return instanceResponseList
}
}
.eraseToAnyPublisher()