В GraphQL возможно ли иметь распознаватели на уровне типа объекта?

1

Мы работаем над довольно сложной схемой GraphQL, где у нас есть несколько типов объектов, которые относятся к различным микросервисам, где каждый тип объекта имеет естественную конечную точку API, которую мы можем запросить. Поэтому было бы очень удобно, если бы можно было определить конкретные резольверы для определенных типов объектов непосредственно, делая что-то вроде этого:

const typeDefs = gql'
    type Query {
      getBook(bookId: ID!): BookPayload
    }

    type BookPayload {
        book: Book
        userErrors: UserError
    }

    type Book {
      id: ID!
      title: String
      author: String
    }
';

const resolvers = {
    Query: {
        getBook: (parent, args, context, info) => {
            return {
                book: { id: args.bookId }
        }
    },
    Book: (parent) => {  // this object type level resolver doesn't seem to work
        return {
            id: parent.id,
            ...fetchBookMetadata(parent.id)
        };
    }
};

Я понимаю, что это тривиальный пример и может показаться немного сконструированным, но он имеет больше смысла (по крайней мере для нас), когда схема начинает становиться очень сложной с сотнями перекрестных ссылок повсюду. Есть ли хороший способ решить это сейчас?

Теги:
graphql
apollo
apollo-server

1 ответ

3
Лучший ответ

Да, вы должны иметь возможность сделать это или что-то очень похожее с помощью директив, проверьте это:

https://www.apollographql.com/docs/graphql-tools/schema-directives.html#Fetching-data-from-a-REST-API

Я буквально отправлю цитату и пример из этой статьи здесь.

Предположим, вы определили тип объекта, который соответствует ресурсу REST, и вы хотите избежать реализации функций распознавателя для каждого поля

const typeDefs = '
directive @rest(url: String) on FIELD_DEFINITION

type Query {
  people: [Person] @rest(url: "/api/v1/people")
}';

class RestDirective extends SchemaDirectiveVisitor {
  public visitFieldDefinition(field) {
    const { url } = this.args;
    field.resolve = () => fetch(url);
  }
}

Согласно спецификации, механизм выполнения GraphQL запускается над наборами наборов, которые разбиваются на отдельные поля. Каждое отдельное поле будет проверяться либо на значение, либо на существующий преобразователь.

Похоже, что если вы определяете директиву, такую как приведенная выше, вы не изменяете это основное поведение, но вы перехватываете и добавляете дополнительный настраиваемый шаг, который должен быть выполнен до дальнейшего разрешения.

Возможно, что-то подобное возможно с пользовательскими скалярами, но это не будет хорошо работать с дизайном схемы.

  • 0
    Нам удалось реализовать это решение, и оно работает довольно хорошо! Спасибо за ваш ответ!

Ещё вопросы

Сообщество Overcoder
Наверх
Меню