我对中继和graphql解析方法感到困惑
Posted
技术标签:
【中文标题】我对中继和graphql解析方法感到困惑【英文标题】:I have confusion on relay and graphql resolve method 【发布时间】:2017-09-08 19:06:39 【问题描述】:抱歉,如果这是一个愚蠢的问题。这是令我困惑的中继/graphql 分页代码:
const GraphQLTodo = new GraphQLObjectType(
name: 'Todo',
fields:
id: globalIdField('Todo'),
text:
type: GraphQLString,
resolve: (obj) => obj.text,
,
complete:
type: GraphQLBoolean,
resolve: (obj) => obj.complete,
,
,
interfaces: [nodeInterface],
);
/* When pagination is needed, make a connection */
const
connectionType: TodosConnection,
edgeType: GraphQLTodoEdge,
= connectionDefinitions(
name: 'Todo',
nodeType: GraphQLTodo,
);
const GraphQLUser = new GraphQLObjectType(
name: 'User',
fields:
id: globalIdField('User'),
todos:
type: TodosConnection,
args:
status:
type: GraphQLString,
defaultValue: 'any',
,
...connectionArgs,
,
resolve: (obj, status, ...args) =>
connectionFromArray(getTodos(status), args),
,
totalCount:
type: GraphQLInt,
resolve: () => getTodos().length,
,
completedCount:
type: GraphQLInt,
resolve: () => getTodos('completed').length,
,
,
interfaces: [nodeInterface],
);
const Root = new GraphQLObjectType(
name: 'Root',
fields:
viewer:
type: GraphQLUser,
resolve: () => getViewer(),
,
node: nodeField,
,
);
你可以看到GraphQLTodo字段有text和complete字段,resolve函数传了一个obj参数,obj是怎么传到那里的?是由 GraphQLUser 解决的吗?我在文档上阅读了 source(在本例中为 obj) - 从父类型的字段解析的对象。不是来自根查询吗?这里的obj是怎么创建的?
【问题讨论】:
【参考方案1】:连接
这里是(部分)魔法发生的地方:
const
connectionType: TodosConnection,
edgeType: GraphQLTodoEdge,
= connectionDefinitions(
name: 'Todo',
nodeType: GraphQLTodo,
);
您现在已经告诉 GraphQL,TodosConnection
将由 GraphQLTodo
节点组成。现在,让我们看看在GraphQLUser
对象中实际为连接获取对象的位置,该对象位于todos
字段中:
todos:
type: TodosConnection,
args:
status:
type: GraphQLString,
defaultValue: 'any',
,
...connectionArgs,
,
resolve: (obj, status, ...args) =>
connectionFromArray(getTodos(status), args),
,
那么这个对象是从哪里来的呢?这里的关键部分是getTodos
函数,它负责从数据源中实际获取对象数组。由于该字段是TodosConnection
,并且我们已经在连接定义中指定节点是GraphQLTodo
s,GraphQL 知道text
和complete
字段是通过获取(在这种情况下)同名来解析的已返回的对象上的字段。换句话说,返回的对象被传递给每个字段的resolve
方法。
查询根目录
Root
上公开了两个字段:viewer
和 node
。暂时忽略node
,您只有一种方法可以实际查询待办事项。由于viewer
是GraphQLUser
类型,而GraphQLUser
具有todos
字段,它们只能作为viewer
的子字段来获取,如下所示:
viewer
todos(first: 10)
edges
# each node is a Todo item
node
text
complete
节点之谜
但是node
字段呢? Relay 希望能够使用***查询获取任何对象,即在您的Root
字段上,当给定一个唯一的globalId
时,它只是类型名称和id 的base64 编码,所以Todo:1
编码为VG9kbzox
。这是在nodeDefinitions
中设置的(您没有包括在此处,但可能有)。在这些定义中,globalId
被解析回type
(Todo
) 和id
(1
),然后再一次告诉它如何从数据源中获取正确的对象。它可能看起来像:
const nodeInterface, nodeField = nodeDefinitions(
(globalId) =>
const type, id = fromGlobalId(globalId);
if (type === 'Todo')
return getTodo(id)
else if (type === 'User')
return getUser(id)
...
因为您在 GraphQLTodo
和 GraphQLUser
类型中都实现了 nodeInterface
,所以 Relay 将能够从 Root
的 node
字段中查询其中任何一个。
【讨论】:
非常感谢,我将在我们的社区页面(facebook)上分享您的答案我希望有一种方式可以与您联系@Eric Streeper以上是关于我对中继和graphql解析方法感到困惑的主要内容,如果未能解决你的问题,请参考以下文章