首页 文章

我对relay和graphql resolve方法感到困惑

提问于
浏览
1

如果这是一个愚蠢的问题,请道歉 . 这是继电器/ 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字段上看到它有文本和完整字段,解析函数传递了一个obj参数,obj是如何传递给那里的?是从GraphQLUser解决?我已经阅读了源文件(在本例中为obj) - 从父类型字段解析的对象 . 它不是来自根查询? obj如何创建?

1 回答

  • 2

    连接

    这是魔术发生的地方(某些):

    const {
      connectionType: TodosConnection,
      edgeType: GraphQLTodoEdge,
    } = connectionDefinitions({
      name: 'Todo',
      nodeType: GraphQLTodo,
    });
    

    您现在告诉GraphQL, TodosConnection 将由 GraphQLTodo 节点组成 . 现在,让我们看一下 todos 对象中 GraphQLUser 对象中为连接实际获取对象的位置:

    todos: {
      type: TodosConnection,
      args: {
        status: {
          type: GraphQLString,
          defaultValue: 'any',
        },
        ...connectionArgs,
      },
      resolve: (obj, {status, ...args}) =>
        connectionFromArray(getTodos(status), args),
    },
    

    那么对象来自哪里?这里的关键部分是 getTodos 函数,它负责从数据源中实际获取对象数组 . 由于此字段是 TodosConnection ,并且我们已在连接定义中指定节点为 GraphQLTodo ,因此GraphQL知道 textcomplete 字段是通过获取(在本例中)已返回的对象上具有相同名称的字段来解析的 . 换句话说,返回的对象将传递给每个字段的 resolve 方法 .

    查询根

    您在 Root 上显示了两个字段: viewernode . 暂时忽略 node ,您只有一种实际查询待办事项的方法 . 由于 viewer 的类型为 GraphQLUserGraphQLUser 具有 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 被解析回 typeTodo )和 id1 ),然后再次告诉它如何从数据源中获取正确的对象 . 它可能看起来像:

    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 字段中查询其中任何一个 .

相关问题