GraphQL中有几个地方需要解析Type
而不只是field
中的Type
。
后端API -
/users
- 用户列表 - 最小信息 - 名称,ID /users/:id
- 详细的用户信息/foo
- 返回字段所有者,即UserID 构建架构以执行以下查询
query a {
users {
age # some detail info
}
foo {
owner {
location # some detail info
}
}
}
,架构可以如下 -
type Query {
users: [User]
foo: Foo
}
type Foo {
owner: User
}
type User {
id: ID
age: Int
location: String
}
上述模式中的解析器需要包含/处理在两个不同位置的用户详细信息获取调用。 1.用户列表 - Query.users
和2. Query.foo.owner
。并且必须记住处理此类型,您只有一个用户ID才能将其转换为实际用户。
在撰写本文时,GraphQL支持resolveType
和Interface
上的Union
。无法为整个Type
指定解析程序 - 只有field
中的Type
才能拥有解析程序。因此,如果可以在GraphQL中解析类型,这将使其更容易实现。
由于只能解析Type中的字段,因此可以创建一个额外的type
并在解析器中的Type中维护此字段的处理,并且位于一个位置。但现在,查询比以前更深了1级。
query b {
users {
details {
age
}
}
foo {
owner {
details {
location
}
}
}
}
由于无法在GraphQL中解析Type
,因此enums
面临同样的问题。当您在API响应中有一个特殊字符并且该字段是ENUM时,您要么记得在使用此枚举的所有位置处理它,要么创建一个额外的类型来表示此枚举。
我使用ApolloGraphQL为所有这些案例创建了一个最小的repro - https://github.com/boopathi/graphql-test-1
答案 0 :(得分:2)
你是对的 - 这在GraphQL中肯定是有点奇怪的。从本质上讲,由于解析器的工作方式,它是来自的类型,而不是转到的类型,它负责获取正确的数据。< / p>
这种方法有利有弊。您可以想象一下GraphQL的实现,其中父对象只返回一个ID,然后您就知道如何获取详细信息的每种类型都有一个解析器。我认为在某些情况下肯定会更好。
以下是我们目前建议如何构建代码以避免这种耦合:
为了实现穷人的依赖注入,我们将它们放在服务器的context
上。当你把它们放在一起时,它看起来像这样:
架构:
# Information about a GitHub repository submitted to GitHunt
type Entry {
# Information about the repository from GitHub
repository: Repository!
# The GitHub user who submitted this entry
postedBy: User!
...
解析器:
export const resolvers = {
Entry: {
repository({ repository_name }, _, context) {
return context.Repositories.getByFullName(repository_name);
},
postedBy({ posted_by }, _, context) {
return context.Users.getByLogin(posted_by);
},
...
您可以在GitHunt-API示例应用中的整个服务器的上下文中看到这一点。
基本上,这种方法使用解析器作为一个瘦包装器来调用底层业务逻辑,就像路由器一样。这与有关服务器at Facebook和otherwise的当前文献一致。