如何在 Apollo graphql 中添加联合类型
How do I add union type in Apollo graphql
我提出这个问题是为了防止有人对如何在 Apollo 中添加 union / Polymorphic 类型感到好奇。希望这会让他们更轻松。
在此示例中,我希望响应为 Worksheet
或 ApiError
// 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)
}))
);
在 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 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
}
}
}
现在您可以检查 __typename
以检查响应中的类型。
Note: For those who are wondering why I'm not using GraphQL errors. It's because Apollo doesn't seem to handle errors well when it encounters a graphQL error. So for a work around I'm trying to return a custom ApiError
in my response.
使用带有错误类型的联合很好的原因有几个。
- 目前如果您想要使用 GraphQLError 的部分响应。 Apollo 不会缓存错误,因此如果您想稍后重新使用缓存的响应,您将无法获得完整的响应,因为错误已被删除。 (现在你不能显示正确的 UI 错误)
- 在 Apollo 中恢复 GraphQLError 将 return 一个简单的错误列表以及数据中错误所在的路径。因此,您需要验证错误发生在架构的哪一部分。但是,如果您按照上述说明进行操作,架构中就会出现错误。这样您就已经知道错误发生在架构的哪一部分。
我提出这个问题是为了防止有人对如何在 Apollo 中添加 union / Polymorphic 类型感到好奇。希望这会让他们更轻松。
在此示例中,我希望响应为 Worksheet
或 ApiError
// 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)
}))
);
在 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 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
}
}
}
现在您可以检查 __typename
以检查响应中的类型。
Note: For those who are wondering why I'm not using GraphQL errors. It's because Apollo doesn't seem to handle errors well when it encounters a graphQL error. So for a work around I'm trying to return a custom
ApiError
in my response.
使用带有错误类型的联合很好的原因有几个。
- 目前如果您想要使用 GraphQLError 的部分响应。 Apollo 不会缓存错误,因此如果您想稍后重新使用缓存的响应,您将无法获得完整的响应,因为错误已被删除。 (现在你不能显示正确的 UI 错误)
- 在 Apollo 中恢复 GraphQLError 将 return 一个简单的错误列表以及数据中错误所在的路径。因此,您需要验证错误发生在架构的哪一部分。但是,如果您按照上述说明进行操作,架构中就会出现错误。这样您就已经知道错误发生在架构的哪一部分。