javascript - 如何使用 express-graphql 抛出多个错误?

标签 javascript graphql graphql-js express-graphql

在 express-graphql 应用程序中,我有一个像这样的 userLogin 解析器:

const userLogin = async ({ id, password }), context, info) => {

    if (!id) {
      throw new Error('No id provided.')
    }

    if (!password) {
      throw new Error('No password provided.')
    }

    // actual resolver logic here
    // … 
}

如果用户没有提供 idpassword,它只会抛出一个错误。

{
  "errors": [
    {
      "message": "No id provided.",
      "locations": [
        {
          "line": 2,
          "column": 3
        }
      ],
      "path": [
        "userLogin"
      ]
    }
  ],
  "data": {
    "userLogin": null
  }
}

如何在 errors 响应数组中抛出多个错误?

最佳答案

没有办法在 JavaScript 中抛出一系列错误,或者让单个解析器拒绝多个错误。 GraphQL 响应包含一个 errors 数组,而不仅仅是一个 error 对象,因为当这些错误源自不同字段时,总响应可以包含多个错误.考虑这个架构和解析器:

type Query {
  a: String
  b: String
  c: String
}

const resolvers = {
  Query: {
    a: () => { throw new Error('A rejected') },
    b: () => { throw new Error('B rejected') },
    c: () => 'Still works!',
  },
}

如果你查询所有三个字段...

查询{ A b C

您的数据将如下所示:

{
  "errors": [
    {
      "message": "A rejected",
      "locations": [
        {
          "line": 2,
          "column": 3
        }
      ],
      "path": [
        "a"
      ]
    },
    {
      "message": "B rejected",
      "locations": [
        {
          "line": 3,
          "column": 3
        }
      ],
      "path": [
        "b"
      ]
    }
  ],
  "data": {
    "a": null,
    "b": null,
    "c": "Still works!"
  }
}

这是因为 GraphQL 支持部分响应。但是,请记住,这是有效的,因为这些字段可以为空。如果它们不为空,这些错误将是 bubble up to the closest nullable parent field .

以下是一些替代方法:

您可以利用 formatError 更改 GraphQL 返回的错误显示给客户端的方式。这意味着您可以在错误中包含任何类型的额外信息,例如错误代码或多条错误消息。一个简单的例子:

// The middleware
app.use('/graphql', graphqlExpress({
    schema: schema,
    formatError: (error) => ({
      message: error.message,
      path: error.path,
      locations: error.locations,
      errors: error.originalError.details
    })
}))

// The error class
class CustomError extends Error {
  constructor(detailsArray) {
    this.message = String(details)
    this.details = details
  }
}

// The resolver
const userLogin = async ({ id, password }), context, info) => {
    const errorDetails = []
    if (!id) errorDetails.push('No id provided.')
    if (!password) errorDetails.push('No password provided.')
    if (errorDetails.length) throw new CustomError(errorDetails)

    // actual resolver logic here
}

您的回复看起来更像这样:

{
  "errors": [
    {
      "message": "[No id provided.,No password provided.]",
      "locations": [
        {
          "line": 2,
          "column": 3
        }
      ],
      "path": [
        "userLogin"
      ]
      "errors" [
        "No id provided.",
        "No password provided."
      ]
    }
  ],
  "data": {
    "userLogin": null
  }
}

也就是说,将面向用户的错误消息与 GraphQL 验证错误一起返回有点令人不快。一些 API 采取的另一种方法是在实际突变响应旁边包含一个 errors 字段。例如:

type Mutation {
  userLogin: UserLoginResponse
}

type UserLoginResponse {
  response: User
  errors: [String!]
}

您还可以使用联合来实现类似的效果:

type Mutation {
  userLogin: UserLoginResponse
}

type Errors {
  errors: [String!]!
}

union UserLoginResponse = User | Errors

关于javascript - 如何使用 express-graphql 抛出多个错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52531894/

相关文章:

javascript - javascript中的字节数组到十六进制字符串的转换

javascript - 在 HTML 中将 UTC 日期转换为本地日期的简洁方法

javascript - "return;"在 javascript 中是什么意思?

amazon-dynamodb - AppSync 中的 DynamoDB 返回值 UPDATED_OLD

javascript - 在 GraphQL 中返回关系数据时遇到问题

javascript - 连接两个 gatsby 节点

javascript - sIFIR 3 显示在我的主页上但没有显示在任何其他页面上

sequelize.js - 如何在 apollo graphql 服务器中编写解析 graphql 过滤器

graphql - 对于 AWS 放大中的架构,graphql 中的数组和映射是否有标量类型?

graphql - 如何使用具有多个突变的自定义文件正确播种 prisma DB?