5

我想知道为什么我的论点似乎在我的 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    
  }`);
4

1 回答 1

3

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

  1. 父字段解析为的值(通常称为objor root
  2. 该字段的参数
  3. 上下文
  4. 描述整个 GraphQL 请求的信息对象

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

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

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

好的,那么根呢?

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

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

那么这里的教训是什么?

不要使用根。

严重地。将您的模式定义为一个对象,或者如果您想使用 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,
})
于 2018-02-06T00:18:06.760 回答