问题
I was thinking about ways of implementing graphql response that would contain both an error and data.
Is it possible to do so without creating a type that would contain error
?
e.g.
Mutation addMembersToTeam(membersIds: [ID!]! teamId: ID!): [Member]
adds members to some team. Suppose this mutation is called with the following membersIds
: [1, 2, 3]
.
Members with ids 1 and 2 are already in the team, so an error must be thrown that these members cannot be added, but member with an id 3 should be added as he is not in the team.
I was thinking about using formatResponse
but seems that I can't get an error there.
Is it possible to solve this problem without adding error field to the return type?
回答1:
Is it possible to solve this problem without adding error field to the return type?
Unfortunately, no.
A resolver can either return data, or return null and throw an error. It cannot do both. To clarify, it is possible to get a partial response and some errors. A simple example:
const typeDefs = `
type Query {
foo: Foo
}
type Foo {
a: String
b: String
}
`
const resolvers = {
Query: {
foo: () => {},
}
Foo: {
a: () => 'A',
b: () => new Error('Oops!'),
}
}
In this example, querying both fields on foo
will result in the following response:
{
"data": {
"foo": {
"a": "A",
"b": null
}
},
"errors": [
{
"message": "Oops",
"locations": [
{
"line": 6,
"column": 5
}
],
"path": [
"foo",
"b"
]
}
]
}
In this way, it's possible to send back both data and errors. But you cannot do so for the same field, like in your question. There's a couple of ways around this. As you point out, you could return the errors as part of the response, which is usually how this is done. You could then use formatResponse
, walk the resulting data, extract any errors and combine them with them with any other GraphQL errors. Not optimal, but it may get you the behavior you're looking for.
Another alternative is to modify the mutation so it takes a single memberId. You can then request a separate mutation for each id you're adding:
add1: addMemberToTeam(memberId: $memberId1 teamId: $teamId): {
id
}
add2: addMemberToTeam(memberId: $memberId2 teamId: $teamId): {
id
}
add3: addMemberToTeam(memberId: $memberId3 teamId: $teamId): {
id
}
This can be trickier to handle client-side, and is of course less efficient, but again might get you the expected behavior.
回答2:
If you think about combining the GraphQL error - there is a way to do it in Apollo.
You need to use errorPolicy
for it. Link for documentation
Setting policy to all
will help you notify users about the error and at the same time have as much data as possible.
none: This is the default policy to match how Apollo Client 1.0 worked. Any GraphQL Errors are treated the same as network errors and any data is ignored from the response.
ignore: Ignore allows you to read any data that is returned alongside GraphQL Errors, but doesn’t save the errors or report them to your UI.
all: Using the all policy is the best way to notify your users of potential issues while still showing as much data as possible from your server. It saves both data and errors into the Apollo Cache so your UI can use them.
But according to best practices, you shouldn't manipulate it in this way. This is a great article about handling errors in GraphQL.
So, preferable way is to add "errors"
field as part of your response and handle it in js code.
来源:https://stackoverflow.com/questions/52778096/how-to-return-both-error-and-data-in-a-graphql-resolver