简体   繁体   English

如何在Apollo graphql中添加联合类型

[英]How do I add union type in Apollo graphql

I created this question in case anyone was curious on how to add union / Polymorphic types in Apollo. 我创建了这个问题,以防有人对如何在Apollo中添加union / Polymorphic类型感到好奇。 Hopefully this will make it easier for them. 希望这会让他们更容易。

In this example I wanted the response to either be a Worksheet or ApiError 在这个例子中,我希望响应是一个WorksheetApiError

// typedefs.js
export default [`
  schema {
    query: Query
  }

  type Query {
    worksheet(id: String!): Worksheet | Error
  }

  type Worksheet {
    id: String!
    name String
  }

  type ApiError {
    code: String!
    message: String!
  }
`];

// resolvers.js
export default {
  Query: {
    worksheet(_, args, { loaders }) {
      return loaders.worksheet.get(args.id).catch(() => {
        // ApiError
        return {
          code: '1',
          message: 'test'
        }
      });
    }
  }
};

// Express Server 
import { graphqlExpress } from 'apollo-server-express';
import { makeExecutableSchema } from 'graphql-tools';
import typeDefs from './typedefs';
import resolvers from './resolvers';

...


app.post(
  '/graphql',
  graphqlExpress(req => ({
    makeExecutableSchema({ typeDefs, resolvers }),
    context: mkRequestContext(req.ctx, req.log),
    formatError: formatGraphQLError(req.ctx, req.log)
  }))
);

In GraphQL to add a union type in the typedefs you have to define the union 在GraphQL中,要在typedef中添加联合类型,您必须定义联合

ie union WorksheetOrError = Worksheet | ApiError union WorksheetOrError = Worksheet | ApiError union WorksheetOrError = Worksheet | ApiError

// typedefs.js
export default [
  `
  schema {
    query: Query
  }

  type Query {
    worksheet(id: String!): WorksheetOrError
  }

  union WorksheetOrError = Worksheet | ApiError 

  type Worksheet {
    id: String!
    name String
  }

  type ApiError {
    code: String!
    message: String!
  }
`];

In the resolvers you have to define a resolver for the union type that has the property __resolveType . 在解析器中,您必须为具有__resolveType属性的union类型定义解析器。 This will help tell the GraphQL executor which type the result is. 这将有助于告诉GraphQL执行程序结果的类型。

 // resolvers.js
export default {
  Query: {
    worksheet() {
      ... 
    }
  },
  WorksheetOrError: {
    __resolveType(obj) {
      if (obj.id) {
        return 'Worksheet';
      }

      if (obj.code) {
        return 'ApiError';
      }

      return null;
    }
  },
};

To create a GraphQL Query in Apollo Client Apollo Client中创建GraphQL查询

// Your application code. 

// This is my Worksheet Query in my React code.
const WorksheetQuery = gql`
  query GetWorksheet($worksheetId: String!) {
    worksheet(id: $worksheetId) {
      ... on Worksheet {
        id
        name
      }
      ... on ApiError {
        code
        message
      }
    }
  }

Now you can check the __typename to check what type is in the response. 现在,您可以检查__typename以检查响应中的类型。

Note: For those who are wondering why I'm not using GraphQL errors . 注意:对于那些想知道我为什么不使用GraphQL错误的人 It's because Apollo doesn't seem to handle errors well when it encounters a graphQL error. 这是因为Apollo在遇到graphQL错误时似乎没有很好地处理错误。 So for a work around I'm trying to return a custom ApiError in my response. 因此,对于一个解决方法,我试图在我的响应中返回自定义ApiError

There a few reasons why using a union with an error type is nice. 使用具有错误类型的联合的原因有几个很好。

  1. Currently if you wanted a partial response with GraphQLError. 目前,如果您想要使用GraphQLError进行部分响应。 Apollo does not cache the errors so if you wanted to re-use the cached response later you wouldn't have the complete response since the errors are removed. Apollo不会缓存错误,因此如果您想稍后重新使用缓存的响应,则会因为错误被删除而无法获得完整的响应。 (Now you can't display the proper UI with errors) (现在您无法显示有错误的正确UI)
  2. Getting GraphQLError back in Apollo would return a flat list of errors with the path to where the error is in the data. 在Apollo中返回GraphQLError将返回错误的平面列表,其中包含错误在数据中的路径。 So you would need to verify that which part of your schema did the error occur in. However if you follow the instructions above you would have the error within the schema already. 因此,您需要验证模式的哪个部分发生了错误。但是,如果您按照上面的说明操作,则会在模式中出现错误。 That way you already know which part of the schema the error happened. 这样你就已经知道错误发生在哪个模式部分。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM