简体   繁体   English

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

[英]How to throw multiple errors with express-graphql?

In an express-graphql app, I have a userLogin resolver like so:在 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
    // … 
}

If the user doesn't provide an id AND a password , it will throw only one error.如果用户没有提供idpassword ,它只会抛出一个错误。

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

How is it possible to throw multiple errors in the errors response array?如何在errors响应数组中抛出多个错误?

There is no way to throw an array of errors in JavaScript or otherwise have a single resolver reject with more than one error.没有办法在 JavaScript 中抛出一系列错误,或者让单个解析器拒绝多个错误。 A GraphQL response includes an errors array and not just a single error object because the total response can include multiple errors when those errors originate from different fields. GraphQL 响应包含一个errors数组,而不仅仅是一个error对象,因为当这些错误源自不同字段时,整个响应可能包含多个错误。 Consider this schema and resolvers:考虑这个模式和解析器:

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!',
  },
}

If you query all three fields...如果您查询所有三个字段...

query { abc }查询 { abc }

Your data will look something like this:您的数据将如下所示:

{
  "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!"
  }
}

This is because GraphQL supports partial responses.这是因为 GraphQL 支持部分响应。 However, keep in mind that this works because the fields are nullable.但是,请记住这是有效的,因为这些字段可以为空。 If they were non-null, those errors would bubble up to the closest nullable parent field .如果它们是非空的,这些错误会冒泡到最近的可为空的父字段

Here are some alternative approaches:以下是一些替代方法:

You can utilize formatError to change how the errors returned by GraphQL are displayed to the client.您可以利用formatError来更改formatError返回的错误显示给客户端的方式。 That means you can include any sort of extra information with your errors, like an error code or multiple error messages.这意味着您可以在错误中包含任何类型的额外信息,例如错误代码或多个错误消息。 A simple example:一个简单的例子:

// 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
}

Your response then looks more like this:您的回复看起来更像这样:

{
  "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
  }
}

That said, there's something a bit unsavory about returning user-facing error messages alongside GraphQL validation errors.也就是说,将面向用户的错误消息与 GraphQL 验证错误一起返回有点令人讨厌。 Another approach that some APIs have taken is to include an errors field alongside the actual mutation response.一些 API 采取的另一种方法是在实际突变响应旁边包含一个errors字段。 For example:例如:

type Mutation {
  userLogin: UserLoginResponse
}

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

You can also use unions to achieve a similar effect:你也可以使用联合来达到类似的效果:

type Mutation {
  userLogin: UserLoginResponse
}

type Errors {
  errors: [String!]!
}

union UserLoginResponse = User | Errors

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

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