在GraphQL中混合模式级错误和应用程序级错误

时间:2016-06-06 19:36:57

标签: graphql relayjs

在graphql API之上构建新应用程序时,我们遇到了以下问题:

我们有一个带有输入字段的变异,其输入字段的类型是具有自己的验证规则的自定义标量(在这种情况下,输入是格式正确的电子邮件地址)。

在客户端上,该应用的用户填写了一堆字段并点击提交。目前,电子邮件地址的验证由GraphQL层处理,如果失败并出现顶级错误,则中止该突变。所有其他字段的验证由突变处理,返回变异有效负载中的应用级错误。在这种情况下,其他验证不能直接在模式中表示,因为它们涉及相互依赖的字段。

这种行为对客户来说真的没有用处:它现在必须知道两个可能位置的错误(顶级graphql错误,以及突变有效负载中的应用程序错误)以及两种可能的格式。这也意味着在修复所有架构级问题之前,不会报告其Graphitive架构中未表示格式错误的其他格式错误的字段,从而迫使用户经历多轮“修复错误,点击提交,得到另一个错误“。

这个问题的标准解决方案是什么?在客户端上进行验证(在这种情况下非常复杂)?削弱架构以便在应用程序层对所有相关验证进行分组?

2 个答案:

答案 0 :(得分:7)

错误分类的问题

  

顶级graphql错误,以及变异有效负载中的应用程序错误

您在架构级别和应用程序级别错误之间的区别是基于GraphQL类型和变异实现。客户端应用程序通常期望更高的抽象级别的错误,即,它需要区分用户错误和系统错误。这样它就可以将系统错误掩盖为“内部错误”,并在必要时显示用户错误。开发人员还可以检查系统错误集。

请参阅Konstantin Tarkus撰写的一篇精美而简洁的文章:Validation and User Errors in GraphQL Mutations,我在这个答案中遵循了这种方法。

一种不那么标准但又有意义的解决方案

据我所知,没有特别的标准方法。但是,您可以尝试以下方法。

首先,在mutation response的顶级字段errors中出现系统级错误

{
  "data": {
    "viewer": {
      "articles": {
        "edges": [
          {
            "node": {
              "title": "Sample article title",
              "tags": null
            }
          }
        ]
      }
    }
  },
  "errors": [
    {
      "message": "Cannot read property 'bar' of undefined",
      "locations": [
        {
          "line": 7,
          "column": 11
        }
      ]
    }
  ]
}

其次,将用户级错误作为单独的字段errors放入突变有效负载中。上述文章的例子:

{
  data: {
    user: null,
    errors: [
      '',
      'Failed to create a new user account.',
      'email',
      'User with this email address was already registered.',
    ]
  }
}
// The errors field is just an array of strings that follows this pattern —
// [argumentName1, errorMessage1, argumentName2, errorMessage2, … ]

上述方法使客户端能够在一个地方查找用户错误 - 突变有效负载的errors字段。它还允许客户端一起接收所有错误。

这种方法失去了突变输入类型的自动验证。但是,验证不会受到影响,因为输入类型的验证逻辑可以放在单独的函数中。此函数将根据需要返回验证错误,最终将放入变异有效负载的errors字段。

顺便说一句,感谢写得好的问题!

答案 1 :(得分:0)

如果您正在使用Apollo,您可以轻松地在graphql响应中复用errors数组,以解决graphql错误和使用此程序包可读取的自定义错误:

https://github.com/thebigredgeek/apollo-errors