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

Мы работаем над довольно сложной схемой 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)
        };
    }
};

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

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
2
0
513
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

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

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

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

Suppose you’ve defined an object type that corresponds to a REST resource, and you want to avoid implementing resolver functions for every field

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 работает с наборами выбора, которые разбиты на отдельные поля. Каждое отдельное поле будет проверяться либо на значение, либо на существующий преобразователь.

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

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

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

Jimmy C 21.09.2018 10:53

Я выпустил директиву, которая делает именно это github.com/gajus/graphql-lazyloader

Gajus 13.11.2020 06:25

Другие вопросы по теме