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

时间:2018-04-23 02:39:52

标签: apollo react-apollo graphql-js apollo-server graphql-tools

我创建了这个问题,以防有人对如何在Apollo中添加 union / Polymorphic类型感到好奇。希望这会让他们更容易。

在此示例中,我希望响应为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)
  }))
);

1 个答案:

答案 0 :(得分:1)

在GraphQL中,要在typedef中添加联合类型,您必须定义 union

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!
  }
`];

在解析器中,您必须为具有 __ resolveType 属性的联合类型定义解析程序。这将有助于告诉GraphQL执行程序结果的类型。

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

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

      return null;
    }
  },
};

Apollo客户端

中创建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
      }
    }
  }

现在,您可以查看__typename以查看响应中的类型。

  

注意:对于那些想知道我为什么不使用 GraphQL错误的人。这是因为Apollo在遇到graphQL错误时似乎没有很好地处理错误。因此,为了解决这个问题,我尝试在我的回复中返回自定义ApiError

使用具有错误类型的联合的原因有几个很好。

  1. 目前,如果您想要使用GraphQLError进行部分响应。 Apollo不会缓存错误,因此如果您想在以后重新使用缓存的响应,那么您将无法获得完整的响应,因为错误已被删除。 (现在您无法显示有错误的正确用户界面)
  2. 在Apollo中返回GraphQLError将返回错误的平面列表,其中包含错误在数据中的路径。因此,您需要验证模式的哪个部分发生了错误。但是,如果您按照上面的说明操作,则会在模式中出现错误。这样,您就已经知道错误发生在架构的哪个部分。