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

时间:2017-04-12 20:28:09

标签: graphql relayjs graphql-js

如果这是一个愚蠢的问题,请道歉。这是继电器/ 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 个答案:

答案 0 :(得分:2)

连接

这是魔法发生的地方(

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,因此GraphQL知道textcomplete字段是通过获取(在这种情况下)已返回的对象上具有相同名称的字段来解决。换句话说,返回的对象将传递给每个字段上的resolve方法。

查询根

Root上有两个字段:viewernode。暂时忽略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被解析回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)
    }
...

由于您在nodeInterfaceGraphQLTodo类型中实施了GraphQLUser,因此Relay可以从Root&#查询其中任何一种39; s node字段。