【问题标题】:Document all potential errors on GraphQL server?记录 GraphQL 服务器上的所有潜在错误?
【发布时间】:2019-08-31 23:49:09
【问题描述】:

对于突变addVoucher,可能发生的潜在错误是有限的。

  • 优惠券代码无效
  • 优惠券已过期
  • 优惠券已兑换

目前,当其中一个发生时,我会抛出一个自定义错误。

// On the server:
const addVoucherResolver = () => {
    if(checkIfInvalid) {
        throw new Error('Voucher code invalid')
    }
    return {
        // data
    }
}

然后在客户端上搜索消息描述,以便提醒用户。然而,这感觉很脆弱,而且 GraphQL API 也不会自动记录潜在的错误。有没有办法定义 GraphQL 模式中的潜在错误?

目前我的架构如下所示:

type Mutation {
    addVoucherResolver(id: ID!): Order
}

type Order {
    cost: Int!
}

如果能做这样的事情就好了:

type Mutation {
    addVoucherResolver(id: ID!): Order || VoucherError
}

type Order {
    cost: Int!
}

enum ErrorType {
    INVALID
    EXPIRED
    REDEEMED
}

type VoucherError {
    status: ErrorType!
}

那么任何使用 API 的人都会知道所有潜在的错误。这对我来说感觉像是一个标准要求,但从阅读来看,似乎没有标准化的 GraphQL 方法。

【问题讨论】:

    标签: graphql


    【解决方案1】:

    可以使用 Union 或 Interface 来完成您想要完成的任务:

    type Mutation {
      addVoucher(id: ID!): AddVoucherPayload
    }
    
    union AddVoucherPayload = Order | VoucherError
    

    您说得对,没有标准化的方法来处理用户可见的错误。对于某些实现,例如apollo-server,可以在响应中返回的错误上公开其他属性,如here 所述。这确实使解析错误更容易,但仍然不理想。

    最近出现了一种“有效负载”模式,用于将这些错误作为架构的一部分进行处理。您可以在 Shopify's 等公共 API 中看到它。我们只使用对象类型,而不是上面示例中的联合:

    type Mutation {
      addVoucher(id: ID!): AddVoucherPayload
      otherMutation: OtherMutationPayload
    }
    
    type AddVoucherPayload {
      order: Order
      errors: [Error!]!
    }
    
    type OtherMutationPayload {
      something: Something
      errors: [Error!]!
    }
    
    type Error {
      message: String!
      code: ErrorCode! # or a String if you like
    }
    
    enum ErrorCode {
      INVALID_VOUCHER
      EXPIRED_VOUCHER
      REDEEMED_VOUCHER
      # etc
    }
    

    一些实现也添加了statussuccess 字段,尽管我发现将实际数据字段(order 是我们的示例)设为可空,然后在突变失败时返回空也足够了。我们甚至可以更进一步,添加一个接口来帮助确保我们的有效负载类型的一致性:

    interface Payload {
      errors: [Error!]!
    }
    

    当然,如果您想更细化并区分不同类型的错误以更好地记录哪个突变可以返回哪组错误,您将无法使用接口。

    我在这种方法上取得了成功,因为它不仅记录了可能的错误,而且使客户更容易处理它们。这也意味着响应返回的任何 other 错误都应立即作为一个危险信号,表明客户端或服务器出现问题。 YMMV。

    【讨论】:

      【解决方案2】:

      您可以使用 graphql 中存在的标量类型 只需写 scalar JSON 并返回任何你想要返回的 JSON 类型。

      `
        scalar JSON
        type Response {
          status: Boolean
          message: String
          data: [JSON]
        }
      `
      

      这是返回响应的 Mutation

        `
        type Mutation {
          addVoucherResolver(id: ID!): Response
        }
      `
      

      你可以从解析器返回

      return {
            status: false,
            message: 'Voucher code invalid(or any error based on condition)',
            data: null
        }
      

      return {
            status: true,
            message: 'Order fetch successfully.',
            data: [{
                object of order
            }]
        }
      

      在前端,您可以使用状态键来识别响应是获取还是发生错误。

      【讨论】:

      • 对于使用 JSON 标量的任何字段,您都会丢失类型验证 :( 在处理无法将响应映射到模式的遗留 API 时,它们很方便,但可能应该谨慎使用。
      • 我们不能在上述解决方案中使用内部对象模式吗?我们也可以使用它映射模式。谢谢。
      • 不太清楚你所说的内部对象模式或映射模式是什么意思。你能澄清你的意思吗?您是否建议使用另一个验证模式,例如使用 Joi 之类的库?
      • 没有。我的意思是数据:[Order] 这样。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-08-20
      • 1970-01-01
      • 1970-01-01
      • 2013-12-29
      • 2012-02-28
      • 2010-09-12
      相关资源
      最近更新 更多