如何防止 运行 基于选择集的解析器?
How can you prevent running a resolver based on the selection set?
示例:
query {
me {
starredPosts {
id
}
}
}
服务器如何注意到只请求了 id,并使用已经获取的 user.starredPosts
(一个 id 数组),而不是为每个 id 调用 Posts.findOne(id)
?
我们遇到了同样的问题,并且正在开源我们在过去一年半的时间里在内部构建的工具来解决这些问题:https://github.com/4Catalyzer/graphql-node-resource/pull/1。
我们使用的解决方案是,对于这样的对象解析器,将它们解析为仅包含 ID 的 "stub" 对象,例如:
const childField = {
type: ChildType,
resolve: obj => ({ id: obj.childId }),
};
然后我们使用 DataLoader
在需要时使用我们自己的默认解析器获取子对象上的附加字段。
我们连接到我们的内部 REST API,它支持对这些请求进行批处理,因此需要额外字段的查询得到高效调度和解析。
但是,这确实会在编写自定义解析器时引入潜在的错误,因为无法保证 obj
实际上具有相关字段。我们通过设置静态类型来解决这个问题,以防止未经检查地访问 obj
.
的属性
您可以检查 info.fieldNodes[0].selectionSet.selections
或使用 graphql-fields
包:
const postsIds = user.starredPosts
const selectionSet = Object.keys(graphqlFields(info))
const onlySelectingId = isEqual(['__typename', 'id'], selectionSet.sort())
if (onlySelectingId) {
return postIds.map(id => ({ id, __typename: 'Post' }))
} else {
return favs.map(id => Post.findOneById(id))
}
示例:
query {
me {
starredPosts {
id
}
}
}
服务器如何注意到只请求了 id,并使用已经获取的 user.starredPosts
(一个 id 数组),而不是为每个 id 调用 Posts.findOne(id)
?
我们遇到了同样的问题,并且正在开源我们在过去一年半的时间里在内部构建的工具来解决这些问题:https://github.com/4Catalyzer/graphql-node-resource/pull/1。
我们使用的解决方案是,对于这样的对象解析器,将它们解析为仅包含 ID 的 "stub" 对象,例如:
const childField = {
type: ChildType,
resolve: obj => ({ id: obj.childId }),
};
然后我们使用 DataLoader
在需要时使用我们自己的默认解析器获取子对象上的附加字段。
我们连接到我们的内部 REST API,它支持对这些请求进行批处理,因此需要额外字段的查询得到高效调度和解析。
但是,这确实会在编写自定义解析器时引入潜在的错误,因为无法保证 obj
实际上具有相关字段。我们通过设置静态类型来解决这个问题,以防止未经检查地访问 obj
.
您可以检查 info.fieldNodes[0].selectionSet.selections
或使用 graphql-fields
包:
const postsIds = user.starredPosts
const selectionSet = Object.keys(graphqlFields(info))
const onlySelectingId = isEqual(['__typename', 'id'], selectionSet.sort())
if (onlySelectingId) {
return postIds.map(id => ({ id, __typename: 'Post' }))
} else {
return favs.map(id => Post.findOneById(id))
}