采用此方案:
union Vehicle = Airplane | Car
type Airplane {
title: String
wingSpan: Int
}
type Car {
title: String
wheels: Int
}
type Person {
vehicle: [Vehicle!]
}
这个查询:
person {
vehicles {
... on Car {
title
wheels
}
... on Airplane {
title
wingSpan
}
}
}
以及这些解析器:
// vehicle-resolver.js
export default {
Vehicle: {
__resolveType(obj) {
if (obj.wheels) {
return "Car"
} else {
return "Airplane"
}
}
}
}
// person-resolver.js
export default {
Person: {
vehicles(obj, args, context) {
// Am I resolving a car or an airplane now - or even both?
// I need to ask my CarService with `obj.personId` or my AirplaneService with `obj.personId` also, but I only want to query it if the query is asking for it.
}
}
}
在我的人 -> 车辆(...)
上,我不确定何时应该查询不同的服务来获取汽车和飞机?在该方法中,我不知道我们正在解析哪种类型。
最佳答案
您将无法知道您的 Union 在解析器内解析 vehicles
的类型。因为__resolveType
字段 Vehicle
实际上取决于它从解析器接收的数据。
听起来您希望客户端能够请求服务器查询此人的汽车或他/她的飞机或两者,然后让服务器采取相应的操作。这通常通过向字段传递参数来完成,例如:
# type definitions
type Person {
vehicles(type: VehicleType): [Vehicle!]
}
enum VehicleType {
CAR
AIRPLANE
}
//resolver
vehicles(obj, { type }, context) {
if (type === 'CAR') // fetch and return cars
if (type === 'AIRPLANE') // fetch and return planes
// otherwise fetch and return both
}
从客户端的 Angular 来看,必须将类型标识为参数 ( type: Car
),然后在条件片段中再次标识类型 ( ... on Car
) 可能有点多余,但这是最简单的解决方案。
或者,您可以采用记录较少的路径,查看客户端在每个请求的基础上实际请求了哪些字段。这可以通过深入研究 fourth argument passed to the resolver function 来完成。 (信息)。我认为使用 Apollo,您应该能够获取如下字段的列表:
info.fieldNodes[0].selectionSet.selections.map(s => s.typeCondition.name.value)
然后您可以检查所请求的类型并让您的解析器采取相应的行动。
但是,采用前一种方式(即向字段添加类型参数)还有一个额外的好处。作为客户,如果我想将查询从获取汽车更改为获取飞机,我不想存储两个(或更多)不同的查询,并且必须根据我想要获取的类型在它们之间切换.
在客户端的上下文中,如果类型是可变的,它可能只是在应用程序状态中保留的变量。那么,作为客户,我宁愿只将该变量与我的查询一起传递。如果我的变量发生变化,我的查询结果也会发生变化,但我不必担心更改查询本身(即它可以包含两种类型的条件片段)。
关于javascript - 在不同解析器上解析联合类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46312796/