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

Ken*_*ong 4 apollo graphql-js apollo-server react-apollo graphql-tools

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

在此示例中,我希望响应为 aWorksheetApiError

// 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)
  }))
);
Run Code Online (Sandbox Code Playgroud)

Ken*_*ong 5

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

IEunion 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!
  }
`];
Run Code Online (Sandbox Code Playgroud)

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

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

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

      return null;
    }
  },
};
Run Code Online (Sandbox Code Playgroud)

在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
      }
    }
  }
Run Code Online (Sandbox Code Playgroud)

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

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

使用带有错误类型的联合有几个好处。

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