Для мутации addVoucher
существует ограниченный список потенциальных ошибок, которые могут возникнуть.
На данный момент я выдаю пользовательскую ошибку, когда происходит одно из них.
// On the server:
const addVoucherResolver = () => {
if (checkIfInvalid) {
throw new Error('Voucher code invalid')
}
return {
// data
}
}
Затем на клиенте я ищу описание сообщения, чтобы предупредить пользователя. Однако это кажется хрупким, а API GraphQL не документирует автоматически потенциальные ошибки. Есть ли способ определить потенциальные ошибки в схеме 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.
Можно использовать Union или Interface, чтобы сделать то, что вы пытаетесь выполнить:
type Mutation {
addVoucher(id: ID!): AddVoucherPayload
}
union AddVoucherPayload = Order | VoucherError
Вы правы в том, что не существует стандартизированного способа обработки ошибок, видимых пользователю. В некоторых реализациях, таких как apollo-server
, можно предоставлять дополнительные свойства ошибкам, возвращаемым в ответе, как описано здесь. Это упрощает синтаксический анализ ошибок, но все же не идеально.
Сравнительно недавно появился шаблон «Полезная нагрузка» для обработки этих ошибок как части схемы. Вы можете видеть это в общедоступных API, таких как Shopify's. Вместо Union, как в примере выше, мы просто используем тип объекта:
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
}
Некоторые реализации также добавляют поле status
или success
, хотя я считаю, что сделать фактическое поле данных (наш пример order
) обнуляемым, а затем вернуть null в случае сбоя мутации также достаточно. Мы можем даже сделать еще один шаг вперед и добавить интерфейс, который поможет обеспечить согласованность между нашими типами полезной нагрузки:
interface Payload {
errors: [Error!]!
}
Конечно, если вы хотите быть более детализированным и различать разные типы ошибок, чтобы лучше документировать, какая мутация может вернуть какой набор ошибок, вы не сможете использовать интерфейс.
Я добился успеха с таким подходом, поскольку он не только документирует возможные ошибки, но и упрощает клиентам работу с ними. Это также означает, что любые ошибки разное, которые возвращаются вместе с ответом, должны служить немедленным сигналом о том, что что-то пошло не так с клиентом или сервером. YMMV.
Вы можете использовать скалярный тип, присутствующий в graphql
просто напишите scalar JSON
и верните любой тип JSON, где вы хотите его вернуть.
`
scalar JSON
type Response {
status: Boolean
message: String
data: [JSON]
}
`
Вот мутация, которая возвращает ответ
`
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, ответы которых нельзя сопоставить со схемой, но в противном случае, вероятно, их следует использовать с осторожностью.