GraphQL 解析器参数(根、参数、上下文)的错误顺序

Posted

技术标签:

【中文标题】GraphQL 解析器参数(根、参数、上下文)的错误顺序【英文标题】:Wrong order of GraphQL resolver arguments (root, args, context) 【发布时间】:2018-07-15 17:58:45 【问题描述】:

我想知道为什么我的论点似乎在我的 GraphQL 解析器中切换了。我正在使用 express-graphql。

一个解析器的示例:

  getLocalDrivers: async (parent, args, ctx) => 
    console.log(ctx);
  

我已经编写了文档中出现的参数名称:http://graphql.org/learn/execution/

但是当我调试和检查对象时,似乎 args 对象是第一个,上下文是第二个,父/根是第三个。

父母:

Object location: "020202"

参数:

IncomingMessage _readableState: ReadableState, readable: false, domain: null, …

上下文:

Object fieldName: "getLocalDrivers", fieldNodes: ....

一些服务器代码:

app.use(
  "/graphql",
  graphqlHTTP(
    schema,
    graphiql: true,
    rootValue: rootResolver
  )
);

我的根解析器:

var rootResolver = 
     getLocalDrivers: async (obj, args, ctx) => 
       console.log(ctx);
  

架构:

var  buildSchema  = require("graphql");
var schema = buildSchema(`
  type Query 
    getLocalDrivers(location: String): [Driver]
  

  type Driver 
    name: String
    location: String    
  `);

【问题讨论】:

【参考方案1】:

如果为某个字段定义了resolve 函数,那么当 GraphQL 解析该字段时,它将向该函数传递 四个 参数:

    父字段解析为的值(通常称为objroot) 该字段的参数 上下文 描述整个 GraphQL 请求的信息对象

如果特定字段没有解析函数,GraphQL 将使用默认解析器,该解析器仅搜索父字段上的属性并在找到时使用该属性。

所以您的getLocalDrivers 查询可以返回Driver 对象的数组,并且只要Driver 对象具有name 属性,name 字段 将解析为该属性的值。

巧合的是,Driver 对象上的 name 属性也可以是一个函数。在这种情况下,GraphQL 会调用该函数来获取它的返回值。与解析器非常相似,GraphQL 将一些信息作为参数传递给该函数,即 1) 参数,2) 上下文和 3) 信息对象。以这种方式解析字段时,省略“obj”参数。

好的,那么根呢?

根对象只是作为“父字段值”提供给查询和突变的对象,这些字段与其他所有字段一样。

因此,如果您还没有为 getLocalDrivers 定义“解析”函数(例如,因为您使用 buildQuery 编译了架构),GraphQL 将使用默认解析器,并使用您传入的根对象作为“父字段值”。它看到了一个getLocalDrivers,但如上所述,因为这是一个函数,它使用上述三个参数调用该函数。

那么这里的教训是什么?

不要使用root。

说真的。将您的架构定义为一个对象,或者如果您想使用 GraphQL 架构语言编写架构,请使用 graphql-tools -- makeExecutableSchema 使处理解析器变得更加容易。

const typeDefs = `
  type Query 
    getLocalDrivers(location: String): [Driver]
  

  type Driver 
    name: String
    location: String    
  
`
const resolvers = 
  Query: 
    getLocalDrivers: (obj, args, ctx) => 
       console.log(obj, args, ctx)
    
  

const schema = makeExecutableSchema(
  typeDefs,
  resolvers,
)

【讨论】:

不幸的是,如果我使用来自 graphql-tools 的 makeExecuteSchema 而不是 buildSchema,我会得到相同的结果。 如果您仍在传递根值,那么您仍然会看到相同的行为。而是将解析器作为解析器对象的一部分传入。我已经用一个例子更新了我的答案。 这次我只是简单地使用 Apollo GraphQL 服务器创建了新服务器,并开始使用 makeExecuteableSchema 使其工作。不过,我的最终解决方案是暂时切换到 Express REST,因为 GraphQL 给我带来了太多问题 :-)

以上是关于GraphQL 解析器参数(根、参数、上下文)的错误顺序的主要内容,如果未能解决你的问题,请参考以下文章

graphql 为啥我需要在解析器参数中声明一个额外的参数

graphql-yoga - GraphQL 解析器参数在哪里定义和记录?

具有多个嵌套解析器并将字段映射到参数的 GraphQL 查询

将接口类型分配给代码优先的 GraphQL 解析器参数

Graphql apollo 服务器解析器参数类型

express-graphql 解析器参数在解析器中为空,但 info variableValues 填充了名称和值