graphqlj-js联合类型,访问参数

时间:2019-04-25 08:58:45

标签: javascript node.js graphql-js

我正在尝试找出如何访问args的{​​{1}}字段。但是,我什至不确定UnionType的retrieveRowsWithoutLocations函数的value参数中包含什么。

我正在查看文档https://graphql.org/graphql-js/type/#graphqluniontype,但是它很简短,并且没有详细说明从何处获取该信息。我尝试查看其他来源,但它们不是graphql-js。

我要执行的操作是访问resolveType并检查其值,然后允许联合决定应返回哪种类型。

args.type


let rows_union =
    new graphql.GraphQLUnionType({
        name: 
            "rows_union",
        types: 
        [
            many_item,
            many_list,
            many_display_list, 
        ],
        resolveType(value) 
        {
            switch(value)
            {
                case "item":
                    return many_item
                case "list":
                    return many_list
                case "display_list":
                    return many_display_list
            }
        }
    })

// Define the Query type
var query =
    new graphql.GraphQLObjectType({
        name: "Query",
        fields:
        {
            retrieveRowsWithoutLocations:
            {
                type:
                    rows_union,
                args:
                {
                    _id:
                    {
                        type:
                            nonNullId()
                    },
                    page:
                    {
                        type:
                            nonNullInt()
                    },
                    page_length:
                    {
                        type:
                            nonNullInt()
                    },
                    type:
                    {
                        type:
                            nonNullString()
                    },
                },
                async resolve ()
                {

                }
            },
        }
    })

let many_type = new graphql.GraphQLObjectType({ name: "many_"+name, fields: { results: { type: graphql.GraphQLList(type) }, total: { type: graphql.GraphQLNonNull(graphql.GraphQLInt) }, } }) 是另一个ObjectType

1 个答案:

答案 0 :(得分:1)

您不能直接访问resolveType(或isTypeOf)内的任何解析程序参数。解析字段后,解析器将返回某个值,或者将解析为该值的Promise。对于返回输出类型,接口或联合的字段,此值应为JavaScript对象。正是这个值传递到resolveType,该值用于确定运行时响应中实际返回的类型。

给出类似的模式

union Animal = Bird | Fish

type Bird {
  numberOfWings: Int
}

type Fish {
  numberOfFins: Int
}

type Query {
  animal: Animal
}

您可以想象animal字段的解析器返回JavaScript对象,例如{ numberOfWings: 2 } { numberOfFins: 4 }。在这里,我们可以利用一种简单的启发式方法来确定类型:

resolveType: (value) => {
  if (value.numberOfWings !== undefined) {
    return 'Bird'
  } else if (value.numberOfFins !== undefined) {
    return 'Fish'
  }
  throw new TypeError(`Unable to resolve type for Animal with value: ${value}`)
}

如果我们返回特定类的实例而不是返回简单对象,则可以做得更好:

resolveType: (value) => {
  if (value instanceof BirdModel) {
    return 'Bird'
  } else if (value instanceof FishModel) {
    return 'Fish'
  }
  throw new TypeError(`Unable to resolve type for Animal with value: ${value}`)
}

无论我们的条件逻辑是什么样的,只要记住我们总是在测试解析器返回的值,无论发生什么情况。

如果您不使用类,并且两个或多个类型共享相同的结构,则事情会变得有些棘手。或者,就像您的情况一样,当区别属性(results)是数组时,因为检查其中一个元素是不行的。想象一下,我们的联合看起来像这样:

union Animal = Cat | Dog

type Cat {
  numberOfPaws: Int
}

type Dog {
  numberOfPaws: Int
}

不幸的是,在这里,我们必须依靠我们的解析器来提供一些其他信息。例如,我们可以返回一些任意字段来标识类型:

// Resolver for animal field
resolve: () => {
  return {
    numberOfPaws: 4,
    kind: 'Dog',
  }
}

// Union
resolveType: (value) => {
  return value.kind
}

但是实际上,我们可以依靠resolveTypeisTypeOf的默认实现来做一个更好的事情:

resolve: () => {
  return {
    numberOfPaws: 4,
    __typename: 'Dog',
  }
}

通过像这样显式返回__typename,我们实际上可以完全省略定义resolveType 。但是,请记住,这再次对解析器产生了依赖性。在可能的情况下,您可能应该更喜欢将resolveTypeinstanceof检查结合使用,而不是将resolveType与解析器逻辑分离。