Мы работаем над довольно сложной схемой 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)
};
}
};
Я понимаю, что это тривиальный пример и может показаться немного излишне продуманным, но он имеет больше смысла (по крайней мере, для нас), когда схема начинает усложняться с сотнями перекрестных ссылок повсюду. Есть ли хороший способ решить эту проблему прямо сейчас?



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Да, вы должны иметь возможность делать это или что-то очень похожее с помощью директив, проверьте это:
Я буквально выложу здесь цитату и пример из этой статьи.
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 работает с наборами выбора, которые разбиты на отдельные поля. Каждое отдельное поле будет проверяться либо на значение, либо на существующий преобразователь.
Кажется, что если вы определяете директиву, подобную приведенной выше, вы не изменяете это базовое поведение, но вы перехватываете и добавляете дополнительный настраиваемый шаг, который должен выполняться перед дальнейшим разрешением.
Возможно, что-то подобное возможно с пользовательскими скалярами, но это не будет хорошо работать с дизайном схемы.
Я выпустил директиву, которая делает именно это github.com/gajus/graphql-lazyloader
Нам удалось реализовать это решение, и оно работает неплохо! Спасибо за ваш ответ!