简体   繁体   English

如何在graphql解析器中同时返回错误和数据?

[英]How to return both error and data in a graphql resolver?

I was thinking about ways of implementing graphql response that would contain both an error and data.我正在考虑实现同时包含错误和数据的 graphql 响应的方法。

Is it possible to do so without creating a type that would contain error ?是否可以在不创建包含error的类型的情况下这样做?

eg例如

Mutation addMembersToTeam(membersIds: [ID!]! teamId: ID!): [Member] adds members to some team.变异addMembersToTeam(membersIds: [ID!]! teamId: ID!): [Member]将成员添加到某个团队。 Suppose this mutation is called with the following membersIds : [1, 2, 3] .假设使用以下membersIds调用此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. ids 1 和 2 的成员已经在团队中,因此必须抛出无法添加这些成员的错误,但应添加 id 3 的成员,因为他不在团队中。

I was thinking about using formatResponse but seems that I can't get an error there.我正在考虑使用formatResponse但似乎我无法在那里得到错误。

Is it possible to solve this problem without adding error field to the return type?是否可以在不向返回类型添加错误字段的情况下解决此问题?

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.解析器可以返回数据,也可以返回 null 并抛出错误。 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:在此示例中,查询foo上的两个字段将导致以下响应:

{
  "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.然后,您可以使用formatResponse ,遍历结果数据,提取任何错误并将它们与任何其他 GraphQL 错误结合起来。 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.另一种选择是修改突变,使其采用单个成员 ID。 You can then request a separate mutation for each id you're adding:然后,您可以为要添加的每个 id 请求单独的更改:

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.这在处理客户端时可能会比较棘手,当然效率也较低,但同样可能会让您获得预期的行为。

If you think about combining the GraphQL error - there is a way to do it in Apollo.如果您考虑合并 GraphQL 错误 - 在 Apollo 中有一种方法可以做到这一点。 You need to set errorPolicy to all .您需要将errorPolicy设置为all That 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. none :这是匹配 Apollo Client 1.0 工作方式的默认策略。 Any GraphQL Errors are treated the same as network errors and any data is ignored from the response.任何 GraphQL 错误都被视为网络错误,并且响应中的任何数据都将被忽略。

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. ignore :忽略允许您读取与 GraphQL 错误一起返回的任何数据,但不会保存错误或将它们报告给您的 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. all :使用 all 策略是通知用户潜在问题的最佳方式,同时仍然显示来自服务器的尽可能多的数据。 It saves both data and errors into the Apollo Cache so your UI can use them.它将数据和错误都保存到 Apollo Cache 中,以便您的 UI 可以使用它们。

But according to best practices, you shouldn't manipulate it in this way.但根据最佳实践,您不应该以这种方式操纵它。 This is a great article about handling errors in GraphQL.这是一篇关于在 GraphQL 中处理错误的好文章

So, preferable way is to add "errors" field as part of your response and handle it in JS code.因此,最好的方法是添加"errors"字段作为响应的一部分并在 JS 代码中处理它。

We can achieve this by using a union.我们可以通过使用联合来实现这一点。 I would recommend visiting the great article Handling GraphQL errors like a champ我建议您访问像冠军一样处理 GraphQL 错误的精彩文章

Example:例子:

Mutation part: We can return the union type for the response & capture the result according to types.

type MemberType {
  id: ID!
  name: String!
}

enum ErrorType {
  BAD_REQUEST_ERROR
  FORBIDDEN_ERROR
  INTERNAL_SERVER_ERROR
  NOT_FOUND_ERROR
  UNAUTHORIZED_ERROR
}

type GraphqlError {
  type: ErrorType!
  code: String!
  message: String!
  helpLink: URL
}


union UserRegisterResult = MemberType | GraphqlError;
addMembersToTeam(membersIds: [ID!]! teamId: ID!): UserRegisterResult!

Response:

addMembersToTeam(membersIds: [ID!]! teamId: ID!): {
...on MemberType{
  id,
  name,
}
...on GraphqlError{
  id,
  message,
  statusCode,
}
}

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

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