子解析器中的 Graphql-Access 参数

Graphql-Access arguments in child resolvers

我正在使用 apollo-server 和 apollo-graphql-tools,我有以下架构

type TotalVehicleResponse {
  totalCars: Int
  totalTrucks: Int
}

type RootQuery {
  getTotalVehicals(color: String): TotalVehicleResponse
}

schema {
  query: RootQuery
}

Resolver函数是这样的

{
  RootQuery: {
    getTotalVehicals: async (root, args, context) => {
      // args = {color: 'something'}
      return {};
    },
    TotalVehicleResponse: {
      totalCars: async (root, args, conext) => {
        // args is empty({}) here
        .........
        .........
      },
      totalTrucks: async (root, args, conext) => {
        // args is empty({}) here
        .........
        .........
      }
    }
  }
}

我的问题是如何在任何子解析器中访问根解析器 (getTotalVehicals) 中可用的 args

args 严格引用查询中对该字段提供的参数。如果您希望子解析器可以使用值,您可以简单地从父解析器 return 它们。

{
  RootQuery: {
    getTotalVehicles: async (root, args, context) => {
      return { color: args.color };
    },
    TotalVehicleResponse: {
      totalCars: async (root, args, context) => {
        // root contains color here
      },
      totalTrucks: async (root, args, context) => {
        // root contains color here
      }
    }
  }
}

如果您知道自己正在使用 variables,除了公认的答案之外,还有另一种方法,即使用解析器函数的第四个参数:info.

info 参数在其他字段中包含一个字段 variableValues。 该字段并不严格包含父级的 args,但如果您的操作是使用传递给父级解析器的变量执行的,那么您将可以通过所有相关的 info.variableValues 访问它们解析器函数。

因此,如果您的操作是这样调用的,例如:

query GetTotalVehicalsOperation($color: String) {
  getTotalVehicals(color: $color) {
    totalCars
    totalTrucks   
  }
}

... 变量:{color: 'something'}

您将可以访问来自其他解析器的变量:

{
  RootQuery: {
    getTotalVehicles: async (root, args, context, info) => {
      //info.variableValues contains {color: 'something'}          
      return {};
    },
    TotalVehicleResponse: {
      totalCars: async (root, args, context, info) => {
        //same here: info.variableValues contains {color: 'something'}
      },
      totalTrucks: async (root, args, context, info) => {
        //and also here: info.variableValues contains {color: 'something'}
      }
    }
  }
}

了解更多关于 变量 在 GraphQL 中的使用

请参考这些 link(您可以在 5 分钟内完成这些 link)

https://graphql.org/learn/queries/#operation-name

https://graphql.org/learn/queries/#variables

https://graphql.org/learn/queries/#fragments

https://graphql.org/learn/queries/#using-variables-inside-fragments

您将更加掌握操作名称、变量、片段以及片段内变量的使用。

看看这个link:https://www.prisma.io/blog/graphql-server-basics-demystifying-the-info-argument-in-graphql-resolvers-6f26249f613a

它将帮助您更多地了解解析器函数的 info 参数。

TLDR:将您的 参数 添加到 字段

(客户端)更改自:

Car(type: $type, materialType: $materialType){
  id
  material
  name
  ...
}

(客户端)收件人:

Car(type: $type){
  id,
  material(materialType: $materialType) // moved here
  name
  ...
}

然后,在您的服务器 fieldResolver 中访问您的参数(在本例中为 material 字段)。

更长的版本

尽量不要通过 root 传递您的参数,除了 IDsarguments that is not from clienta parent object,其他任何使用 字段级参数 (除非你有非常好的理由不

为什么?

有几个原因:

  1. 紧耦合

    它会导致耦合并且很难扩展模式 - 来自评论区的@Bruno Ribeiro:

  2. 难以排除故障

    一个级别还是可以的,但是当你公司的某个人找到了一种方法将论点深入到根源时,很难调试它是如何丢失的。

  3. 向children

    泄露不必要的信息

    通过 root 传递参数也意味着传递给每个其他 child,无论是否需要。

  4. 混淆了parentobject和参数

    您的 parent object 可能与参数具有相同的 属性 键,例如:offset,通过提供另一个偏移量,您可能会得到不希望的结果。

如何?

一个简单的查询可以由此增长:

[Root] Car(
  color:white, 
  type:sedan, 
  seat:leather
) {
  id,
  seat,
  numberOfPassengers,
  ...
}

为此:

[Root] Car(
  color:white, 
  type:sedan, 
  seat:leather, 
  seatColor:black,
  rimColor: blue,
  rimShape: OutOfTheWorld,
  ...
) {
  id,
  seat,
  numberOfPassengers,
  ...
}

您可以这样做,而不是四处传递参数

[Root] Car(
  color:white, 
  type:sedan
  ...
) {
  id
  seat(type:leather, color:black),
  rim(color: blue, shape: OutOfTheWorld){
    // nested query
    material(hardness: high), // solved `Why no.2`: deep argument. 
    
    // More nested
    brand(trustWorthy: high) {
      priceRange(range: mid),
      area,
      ...
    },
    id
  }
  numberOfPassengers,
  ...
}

现在每个字段都负责其参数和解析器,而不是将所有参数集中到一个根中。

什么时候申请?

每当您发现自己为该字段创建专用解析器时,将参数传递给该字段(不是根,更糟的是:信息)