是否可以从 Relay 突变访问 GraphQL 验证错误?

Posted

技术标签:

【中文标题】是否可以从 Relay 突变访问 GraphQL 验证错误?【英文标题】:Is it possible to accessing GraphQL validation errors from a Relay mutation? 【发布时间】:2020-10-15 12:28:15 【问题描述】:

我对 GraphQL 有点陌生,所以,我仍然在脑海中将所有活动部分拼凑在一起。

在我的服务器端,我使用TypeGraphQL,它使用class-validator 来验证传入的查询。在客户端,我使用的是中继。当验证失败时,我在 Relay 中的 commitMutation 调用调用 onError 并传递错误的字符串表示,但来自服务器的实际响应如下所示:


  "errors": [
    
      "message": "Argument Validation Error",
      "locations": [
        
          "line": 2,
          "column": 3
        
      ],
      "path": [
        "updateCurrentUser"
      ],
      "extensions": 
        "code": "INTERNAL_SERVER_ERROR",
        "exception": 
          "validationErrors": [
            
              "target": 
                "name": "ueoa",
                "nickname": "ueoa",
                "email": ""
              ,
              "value": "",
              "property": "email",
              "children": [],
              "constraints": 
                "isEmail": "email must be an email"
              
            
          ],
          "stacktrace": [
            "Error: Argument Validation Error",
            "    at Object.validateArg (C:\\Users\\pupeno\\Documents\\Flexpoint Tech\\imok\\node_modules\\type-graphql\\dist\\resolvers\\validate-arg.js:24:15)",
            "    at runMicrotasks (<anonymous>)",
            "    at processTicksAndRejections (internal/process/task_queues.js:97:5)",
            "    at async Promise.all (index 0)"
          ]
        
      
    
  ],
  "data": null

在这种情况下,我将电子邮件留空,因此在 errors[0].extensions.exception.validationErrors[0].constraints.isEmail 上出现错误:“电子邮件必须是电子邮件”。

Relay 有没有办法让我访问这个结构来将这个错误转化为用户的 UI 错误?或者这些错误是否相当于 500,我应该实现自己的单独错误处理(相当于 401)?

我的大部分验证都是在客户端上完成的,但唯一性只能在服务器上完成,我正在尝试找出两者之间的协议。

【问题讨论】:

【参考方案1】:

我对 relay 了解不多,但我使用 Typegraphql 有一段时间了。我可以说的是,来自 class-validator 的错误与标准错误的嵌套不同(我说的是throw new Error('this will be different')。我建议您在后端有一个错误格式化程序功能,以便无论抛出什么类型的错误,您都可以返回一个标准的 graphql 错误。在 apollo 服务器中,有一个格式化错误的选项,我相信其他 graphql 服务器也有。这是它的外观

  const apolloServer = new ApolloServer(
    formatError: (error) => error, 
  );

如果抛出 class-validator's 错误,则上面的错误将是 ArgumentValidationError 因此,如果错误是 ArgumentValidationError 的实例,您需要对其进行正确格式化并返回客户端并提取所有约束值并附加在 message 字段上。这样,所有错误在前端的行为都会相同。

【讨论】:

【参考方案2】:

当涉及到graphQL 时,确实很难处理错误,因为在结果结束时您将获得 200 个 OK 响应。

您遇到的这些错误是INTERNAL SERVER ERROR,相当于500。 因此,在这种情况下,您需要自己处理。

正如 Nux 所写,Apollo 有错误处理模块,您可以参考 here 这可能会有所帮助。

此外,正如您提到的,您正在从客户端进行大部分验证,因此仅在客户端进行验证并不是一个好主意,因为它可能会出现问题并可能成为主要违规行为。

【讨论】:

以上是关于是否可以从 Relay 突变访问 GraphQL 验证错误?的主要内容,如果未能解决你的问题,请参考以下文章

在创建模型的 GraphQL/Relay 突变中,有没有办法取回模型 ID?

如何订阅relay/graphql突变的进度事件

如何进行示例 GraphQL Relay 突变

如何在 Relay 中捕获和处理失败的突变?

给定 GraphQL 模式,是不是可以进行客户端预突变验证?

React Relay:复杂的突变脂肪查询