【问题标题】:I have confusion on relay and graphql resolve method我对中继和graphql解析方法感到困惑
【发布时间】: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是怎么创建的?

【问题讨论】:

    标签: graphql relayjs graphql-js


    【解决方案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,并且我们已经在连接定义中指定节点是GraphQLTodos,GraphQL 知道textcomplete 字段是通过获取(在这种情况下)同名来解析的已返回的对象上的字段。换句话说,返回的对象被传递给每个字段的resolve 方法。

    查询根目录

    Root 上公开了两个字段:viewernode。暂时忽略node,您只有一种方法可以实际查询待办事项。由于viewerGraphQLUser 类型,而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)
        }
    ...
    

    因为您在 GraphQLTodoGraphQLUser 类型中都实现了 nodeInterface,所以 Relay 将能够从 Rootnode 字段中查询其中任何一个。

    【讨论】:

    • 非常感谢,我将在我们的社区页面(facebook)上分享您的答案我希望有一种方式可以与您联系@Eric Streeper
    猜你喜欢
    • 2017-03-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-27
    • 1970-01-01
    • 2019-09-22
    • 2013-07-19
    相关资源
    最近更新 更多